Compare commits
14 commits
Author | SHA1 | Date | |
---|---|---|---|
f2876aef0a | |||
783b4eb385 | |||
49a182b62b | |||
0929f7af0a | |||
5be29c891a | |||
12799eb70d | |||
cd776ffbac | |||
0b23413453 | |||
445b4d720e | |||
b8bcfbf0a9 | |||
96c45ef0ee | |||
de33267ca1 | |||
3f49c81481 | |||
43d37a9d24 |
14 changed files with 291 additions and 169 deletions
|
@ -1,10 +1,10 @@
|
||||||
FROM python:3
|
FROM python:3.12-alpine
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
RUN mkdir /dislocker
|
RUN mkdir /dislocker
|
||||||
|
|
||||||
ENV TZ JST-9
|
RUN apk --no-cache add tzdata
|
||||||
ENV TERM xterm
|
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
|
||||||
|
|
||||||
RUN pip install --upgrade pip
|
RUN pip install --upgrade pip
|
||||||
RUN pip install --upgrade setuptools
|
RUN pip install --upgrade setuptools
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
FROM python:3
|
FROM python:3.12-alpine
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
RUN mkdir /dislocker
|
RUN mkdir /dislocker
|
||||||
|
|
||||||
ENV TZ JST-9
|
RUN apk --no-cache add tzdata
|
||||||
ENV TERM xterm
|
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
|
||||||
|
|
||||||
RUN pip install --upgrade pip
|
RUN pip install --upgrade pip
|
||||||
RUN pip install --upgrade setuptools
|
RUN pip install --upgrade setuptools
|
||||||
|
|
|
@ -34,8 +34,6 @@ services:
|
||||||
- TZ=Asia/Tokyo
|
- TZ=Asia/Tokyo
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/db:/var/lib/postgresql/data
|
- ./data/db:/var/lib/postgresql/data
|
||||||
ports:
|
|
||||||
- 12245:5432
|
|
||||||
env_file:
|
env_file:
|
||||||
- ./data/.env
|
- ./data/.env
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import psycopg2
|
import psycopg2
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from flask import Flask, request, jsonify, render_template
|
from flask import Flask, request, jsonify, render_template, redirect
|
||||||
import uuid
|
import uuid
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
|
@ -338,6 +338,11 @@ class Auth():
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
def get_pc_list(self, **kwargs):
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
cursor.execute('SELECT pc_number, alt_name, master_password FROM pc_list ORDER BY pc_number')
|
||||||
|
pc_list = cursor.fetchall()
|
||||||
|
return pc_list
|
||||||
|
|
||||||
app = Flask(__name__, static_folder="./resource/")
|
app = Flask(__name__, static_folder="./resource/")
|
||||||
auth = Auth(server_config["db"]["host"], server_config["db"]["db_name"], server_config["db"]["port"], server_config["db"]["username"], server_config["db"]["password"])
|
auth = Auth(server_config["db"]["host"], server_config["db"]["db_name"], server_config["db"]["port"], server_config["db"]["username"], server_config["db"]["password"])
|
||||||
|
@ -479,6 +484,33 @@ def device_register():
|
||||||
else:
|
else:
|
||||||
return jsonify({'message': 'damedesu'}), 401
|
return jsonify({'message': 'damedesu'}), 401
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
return redirect('/admin')
|
||||||
|
|
||||||
|
@app.route('/admin')
|
||||||
|
def admin():
|
||||||
|
return render_template('admin.html')
|
||||||
|
|
||||||
|
@app.route('/admin/pc_list')
|
||||||
|
def admin_pclist():
|
||||||
|
table = '<table id="pc_list_table"><thead><tr><th>PC番号</th><th>ニックネーム</th><th>マスターパスワード</th></tr></thead><tbody>'
|
||||||
|
pc_list = auth.get_pc_list()
|
||||||
|
for i in pc_list:
|
||||||
|
pc_number = i[0]
|
||||||
|
alt_name = i[1]
|
||||||
|
if alt_name == None:
|
||||||
|
alt_name = '-ニックネーム未登録-'
|
||||||
|
|
||||||
|
master_password = i[2]
|
||||||
|
if master_password == None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
table += f'<tr><td>{pc_number}</td><td>{alt_name}</td><td>{master_password}</td></tr>'
|
||||||
|
|
||||||
|
table += '</tbody></table>'
|
||||||
|
|
||||||
|
return render_template('pc_list.html', pc_list_table=table)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host="0.0.0.0", port=5000, debug=False)
|
app.run(host="0.0.0.0", port=5000, debug=False)
|
|
@ -12,7 +12,6 @@ import random
|
||||||
import tkinter
|
import tkinter
|
||||||
import threading
|
import threading
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
|
||||||
import uuid
|
import uuid
|
||||||
import time
|
import time
|
||||||
import win32com.client
|
import win32com.client
|
||||||
|
@ -31,6 +30,9 @@ sp_startupinfo.wShowWindow = subprocess.SW_HIDE
|
||||||
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
|
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
|
||||||
config_dir_path = "./config/"
|
config_dir_path = "./config/"
|
||||||
client_config_path = config_dir_path + "client.json"
|
client_config_path = config_dir_path + "client.json"
|
||||||
|
lang_dir_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "lang")
|
||||||
|
lang_path = lang_dir_path + "\\lang_client.json"
|
||||||
|
|
||||||
if not os.path.isfile(client_config_path):
|
if not os.path.isfile(client_config_path):
|
||||||
if not os.path.isdir(config_dir_path):
|
if not os.path.isdir(config_dir_path):
|
||||||
os.mkdir(config_dir_path)
|
os.mkdir(config_dir_path)
|
||||||
|
@ -50,13 +52,24 @@ if not os.path.isfile(client_config_path):
|
||||||
},
|
},
|
||||||
"pc_uuid": "",
|
"pc_uuid": "",
|
||||||
"pc_token": "",
|
"pc_token": "",
|
||||||
"hard_lock": False
|
"hard_lock": False,
|
||||||
|
"cover_image": "dislocker",
|
||||||
|
"language": "ja"
|
||||||
}
|
}
|
||||||
|
|
||||||
elif os.path.isfile(client_config_path):
|
elif os.path.isfile(client_config_path):
|
||||||
with open(client_config_path, "r") as r:
|
with open(client_config_path, "r", encoding="utf-8") as r:
|
||||||
client_config = json.load(r)
|
client_config = json.load(r)
|
||||||
|
|
||||||
|
if os.path.isfile(lang_path):
|
||||||
|
with open(lang_path, "r", encoding="utf-8") as r:
|
||||||
|
lang_json = json.load(r)
|
||||||
|
lang = lang_json[client_config["language"]]
|
||||||
|
else:
|
||||||
|
print("言語ファイルが見つかりません。")
|
||||||
|
lang_not_found = tkinter.messagebox.showerror(title=f"{app_name} | 重大なエラー", message=f"言語ファイルが見つかりません。\n言語ファイルが削除されているか、ファイル名が間違っている可能性があります。\n{app_name} は起動できません。")
|
||||||
|
|
||||||
|
|
||||||
def get_input_devices():
|
def get_input_devices():
|
||||||
str_computer = "."
|
str_computer = "."
|
||||||
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||||
|
@ -126,13 +139,13 @@ def init(**kwargs):
|
||||||
if "pc_number" in kwargs:
|
if "pc_number" in kwargs:
|
||||||
client_config["pc_number"] = int(kwargs["pc_number"])
|
client_config["pc_number"] = int(kwargs["pc_number"])
|
||||||
else:
|
else:
|
||||||
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
|
tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["not_found_pc_number"]["title"]}", message=f"{lang["init"]["msgbox"]["not_found_pc_number"]["details"]}")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
if "onetime" in kwargs:
|
if "onetime" in kwargs:
|
||||||
onetime = str(kwargs["onetime"])
|
onetime = str(kwargs["onetime"])
|
||||||
else:
|
else:
|
||||||
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
|
tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["not_found_onetime_password"]["title"]}", message=f"{lang["init"]["msgbox"]["not_found_onetime_password"]["details"]}")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
if "host_url" in kwargs:
|
if "host_url" in kwargs:
|
||||||
|
@ -150,7 +163,7 @@ def init(**kwargs):
|
||||||
responce = requests.post(register_url, json=register_json)
|
responce = requests.post(register_url, json=register_json)
|
||||||
|
|
||||||
if responce.status_code == 200:
|
if responce.status_code == 200:
|
||||||
print("PCの情報が登録されました。")
|
print(f"{lang["init"]["print"]["init_ok"]}")
|
||||||
responce_json = responce.json()
|
responce_json = responce.json()
|
||||||
pc_token = str(responce_json["pc_token"])
|
pc_token = str(responce_json["pc_token"])
|
||||||
master_password_hash = str(responce_json["master_password_hash"])
|
master_password_hash = str(responce_json["master_password_hash"])
|
||||||
|
@ -158,23 +171,23 @@ def init(**kwargs):
|
||||||
client_config["pc_token"] = pc_token
|
client_config["pc_token"] = pc_token
|
||||||
client_config["master_password_hash"] = master_password_hash
|
client_config["master_password_hash"] = master_password_hash
|
||||||
|
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nBotが起動している場合は、管理者がDiscordから確認することもできます。\n\n{master_password}\n\n")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["init"]["msgbox"]["init_ok"]["title"]}", message=f"{lang["init"]["msgbox"]["init_ok"]["details"]}\n\n{master_password}\n\n")
|
||||||
client_config["initial"] = False
|
client_config["initial"] = False
|
||||||
|
|
||||||
with open(client_config_path, "w") as w:
|
with open(client_config_path, "w", encoding="utf-8") as w:
|
||||||
json.dump(client_config, w, indent=4)
|
json.dump(client_config, w, indent=4, ensure_ascii=False)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
elif responce.status_code == 400:
|
elif responce.status_code == 400:
|
||||||
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\n指定されたPC番号には既に登録されています。PCを置き換えたい場合は、Botから登録を解除してください。")
|
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["exist_pc_number"]["title"]}", message=f"{lang["init"]["msgbox"]["exist_pc_number"]["details"]}")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
elif responce.status_code == 401:
|
elif responce.status_code == 401:
|
||||||
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。")
|
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["wrong_onetime_password"]["title"]}", message=f"{lang["init"]["msgbox"]["wrong_onetime_password"]["details"]}")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
elif responce.status_code == 500:
|
elif responce.status_code == 500:
|
||||||
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nサーバーで内部エラーが発生しています。")
|
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["internal_error"]["title"]}", message=f"{lang["init"]["msgbox"]["internal_error"]["details"]}")
|
||||||
return 2
|
return 2
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
@ -199,9 +212,9 @@ class App(customtkinter.CTk):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
signout_session = subprocess.run('shutdown /l /f /t 3', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
|
signout_session = subprocess.run('shutdown /l /f /t 3', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
|
||||||
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 初回処理のエラー", message=f"初回処理の実行にエラーが発生しました。\n自動的にサインアウトされます。")
|
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["App"]["msgbox"]["init_error"]["title"]}", message=f"{lang["App"]["msgbox"]["init_error"]["details"]}")
|
||||||
|
|
||||||
self.title(f"{app_name} | ロック中")
|
self.title(f"{app_name} | {lang["App"]["title"]}")
|
||||||
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
|
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
|
||||||
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
||||||
self.frame.grid(row=0, column=0, sticky='nsew')
|
self.frame.grid(row=0, column=0, sticky='nsew')
|
||||||
|
@ -237,10 +250,10 @@ class App(customtkinter.CTk):
|
||||||
|
|
||||||
def toast(self):
|
def toast(self):
|
||||||
success = Notification(
|
success = Notification(
|
||||||
app_id='Dislocker',
|
app_id=f'{app_name}',
|
||||||
title='ご協力ありがとうございます!',
|
title=f'{lang["App"]["notification"]["success"]["title"]}',
|
||||||
msg='パスワード認証に成功しました。\n現在使われたパスワードは削除されます。',
|
msg=f'{lang["App"]["notification"]["success"]["details"]}',
|
||||||
icon=resource_path + r'\success.png'
|
icon=resource_path + '\\icon\\success.png'
|
||||||
)
|
)
|
||||||
success.set_audio(audio.Default, loop=False)
|
success.set_audio(audio.Default, loop=False)
|
||||||
success.show()
|
success.show()
|
||||||
|
@ -253,9 +266,9 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
if client_config["testing"] == True:
|
if client_config["testing"] == True:
|
||||||
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | テストモード')
|
self.title(f'{app_name} | {lang["Lock"]["gui"]["pc_number"]} {client_config["pc_number"]} | {lang["Lock"]["gui"]["testing"]}')
|
||||||
else:
|
else:
|
||||||
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | ロックされています')
|
self.title(f'{app_name} | {lang["Lock"]["gui"]["pc_number"]} {client_config["pc_number"]} | {lang["Lock"]["gui"]["locked"]}')
|
||||||
|
|
||||||
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
|
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
|
||||||
self.window_width = 760
|
self.window_width = 760
|
||||||
|
@ -280,7 +293,7 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
self.textbox_font = customtkinter.CTkFont(family="meiryo", size=14)
|
self.textbox_font = customtkinter.CTkFont(family="meiryo", size=14)
|
||||||
self.button_font = customtkinter.CTkFont(family="meiryo", size=14)
|
self.button_font = customtkinter.CTkFont(family="meiryo", size=14)
|
||||||
|
|
||||||
self.cover_img = customtkinter.CTkImage(light_image=Image.open(resource_path + '\\cover\\dislocker_light.png'), dark_image=Image.open(resource_path + '\\cover\\dislocker_dark.png'), size=(160, 320))
|
self.cover_img = customtkinter.CTkImage(light_image=Image.open(f'{resource_path}\\cover\\{client_config["cover_image"]}\\light.png'), dark_image=Image.open(f'{resource_path}\\cover\\{client_config["cover_image"]}\\dark.png'), size=(160, 320))
|
||||||
|
|
||||||
self.grid_columnconfigure(0, weight=1)
|
self.grid_columnconfigure(0, weight=1)
|
||||||
self.grid_columnconfigure(1, weight=6)
|
self.grid_columnconfigure(1, weight=6)
|
||||||
|
@ -294,33 +307,30 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
||||||
self.msg_title_frame.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
|
self.msg_title_frame.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
|
||||||
|
|
||||||
#self.icon_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text='😎', font=self.emoji_font, justify="left")
|
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'{lang["Lock"]["gui"]["msg_title_1"]}', font=self.title_font, justify="left")
|
||||||
#self.icon_title_1.grid(row=0, column=0, padx=10, sticky="w")
|
|
||||||
|
|
||||||
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'ちょっと待って!! ', font=self.title_font, justify="left")
|
|
||||||
self.msg_title_1.grid(row=0, column=0, padx=10, sticky="we")
|
self.msg_title_1.grid(row=0, column=0, padx=10, sticky="we")
|
||||||
|
|
||||||
self.pc_number_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'PC番号 | {client_config["pc_number"]}', font=self.title_font, justify="right")
|
self.pc_number_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'{lang["Lock"]["gui"]["pc_number_title_1"]} | {client_config["pc_number"]}', font=self.title_font, justify="right")
|
||||||
self.pc_number_title_1.grid(row=0, column=1, padx=10, sticky="e")
|
self.pc_number_title_1.grid(row=0, column=1, padx=10, sticky="e")
|
||||||
|
|
||||||
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text="本当にあなたですか?", font=self.title_small_font, justify="left")
|
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text=f"{lang["Lock"]["gui"]["msg_title_2"]}", font=self.title_small_font, justify="left")
|
||||||
self.msg_title_2.grid(row=1, column=0, padx=10, columnspan=2, sticky="w")
|
self.msg_title_2.grid(row=1, column=0, padx=10, columnspan=2, sticky="w")
|
||||||
|
|
||||||
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
||||||
self.msg_subtitle_frame.grid(row=1, column=1, padx=10, pady=0, sticky="nsew")
|
self.msg_subtitle_frame.grid(row=1, column=1, padx=10, pady=0, sticky="nsew")
|
||||||
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
|
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
|
||||||
|
|
||||||
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='サインインするには、Discordを開き、Dislockerから送信された\nパスワードを入力してください。', font=self.general_font, justify="left")
|
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text=f'{lang["Lock"]["gui"]["msg_subtitle_1"]}', font=self.general_font, justify="left")
|
||||||
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="w")
|
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="w")
|
||||||
|
|
||||||
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='※ パスワードの有効期限は発行から5分間です。期限が切れた場合は、もう一度発行してください。', font=self.general_small_font, justify="left")
|
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text=f'{lang["Lock"]["gui"]["msg_subtitle_2"]}', font=self.general_small_font, justify="left")
|
||||||
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
|
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
|
||||||
|
|
||||||
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
|
||||||
self.input_frame.grid(row=2, column=1, padx=10, pady=0, sticky="nsew")
|
self.input_frame.grid(row=2, column=1, padx=10, pady=0, sticky="nsew")
|
||||||
self.input_frame.columnconfigure(0, weight=1)
|
self.input_frame.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text='パスワード', show='*', font=self.textbox_font)
|
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text=f'{lang["Lock"]["gui"]["password_entry"]}', show='*', font=self.textbox_font)
|
||||||
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
|
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
|
||||||
self.password_entry.bind("<Return>", self.auth_start_ev)
|
self.password_entry.bind("<Return>", self.auth_start_ev)
|
||||||
|
|
||||||
|
@ -330,13 +340,13 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
self.button_frame.columnconfigure(1, weight=1)
|
self.button_frame.columnconfigure(1, weight=1)
|
||||||
self.button_frame.columnconfigure(2, weight=1)
|
self.button_frame.columnconfigure(2, weight=1)
|
||||||
|
|
||||||
self.signin_button = customtkinter.CTkButton(self.button_frame, text='サインイン', command=self.auth_start, font=self.button_font)
|
self.signin_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["signin_button"]}', command=self.auth_start, font=self.button_font)
|
||||||
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
|
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
|
||||||
|
|
||||||
self.signout_button = customtkinter.CTkButton(self.button_frame, text='サインアウト', command=self.signout, font=self.button_font)
|
self.signout_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["signout_button"]}', command=self.signout, font=self.button_font)
|
||||||
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
|
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
|
||||||
|
|
||||||
self.help_button = customtkinter.CTkButton(self.button_frame, text='ヘルプ', command=self.help_dummy, font=self.button_font)
|
self.help_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["help_button"]}', command=self.help_dummy, font=self.button_font)
|
||||||
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
|
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
|
||||||
|
|
||||||
self.keyboard_listener_thread = threading.Thread(target=self.keyboard_listener)
|
self.keyboard_listener_thread = threading.Thread(target=self.keyboard_listener)
|
||||||
|
@ -407,20 +417,20 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
devices = []
|
devices = []
|
||||||
|
|
||||||
if len(password) == 10:
|
if len(password) == 10:
|
||||||
print("マスターパスワードで認証を試行します。")
|
print(f'{lang["Lock"]["auth"]["print"]["try_master_password"]}')
|
||||||
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
|
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
|
||||||
if client_config["master_password_hash"] == master_password_hash:
|
if client_config["master_password_hash"] == master_password_hash:
|
||||||
print("マスターパスワードで認証しました。")
|
print(f'{lang["Lock"]["auth"]["print"]["success_master_password"]}')
|
||||||
self.exit()
|
self.exit()
|
||||||
else:
|
else:
|
||||||
print("マスターパスワードで認証できませんでした。")
|
print(f'{lang["Lock"]["auth"]["print"]["error_master_password"]}')
|
||||||
self.withdraw()
|
self.withdraw()
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["wrong_password"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["wrong_password"]["details"]}")
|
||||||
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
|
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["wrong_password"]}')
|
||||||
self.button_enable()
|
self.button_enable()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
|
|
||||||
print("認証サーバーにアクセスします。")
|
print(f'{lang["Lock"]["auth"]["print"]["access_auth_server"]}')
|
||||||
auth_url = client_config["auth_host_url"] + "/verify"
|
auth_url = client_config["auth_host_url"] + "/verify"
|
||||||
auth_json = {
|
auth_json = {
|
||||||
"pc_number": int(client_config["pc_number"]),
|
"pc_number": int(client_config["pc_number"]),
|
||||||
|
@ -432,33 +442,33 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
try:
|
try:
|
||||||
responce = requests.post(auth_url, json=auth_json)
|
responce = requests.post(auth_url, json=auth_json)
|
||||||
if responce.status_code == 200:
|
if responce.status_code == 200:
|
||||||
print("認証サーバー経由で認証しました。")
|
print(f'{lang["Lock"]["auth"]["print"]["success_auth_server"]}')
|
||||||
self.exit()
|
self.exit()
|
||||||
elif responce.status_code == 401:
|
elif responce.status_code == 401:
|
||||||
print("認証サーバー経由での認証に失敗しました。")
|
print(f'{lang["Lock"]["auth"]["print"]["error_wrong_password"]}')
|
||||||
self.withdraw()
|
self.withdraw()
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["wrong_password"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["wrong_password"]["details"]}")
|
||||||
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
|
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["wrong_password"]}')
|
||||||
self.button_enable()
|
self.button_enable()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
elif responce.status_code == 500:
|
elif responce.status_code == 500:
|
||||||
print("内部エラーにより認証に失敗しました。")
|
print(f'{lang["Lock"]["auth"]["print"]["error_internal_server"]}')
|
||||||
self.withdraw()
|
self.withdraw()
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 内部エラー", message=f"サーバーの内部エラーにより認証に失敗しました。")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["internal_error"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["internal_error"]["details"]}")
|
||||||
self.msg_subtitle_1.configure(text='内部エラーにより認証に失敗しました。 ')
|
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["internal_error"]}')
|
||||||
self.button_enable()
|
self.button_enable()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
except:
|
except:
|
||||||
print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。")
|
print(f'{lang["Lock"]["auth"]["print"]["cant_access_auth_server"]}')
|
||||||
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
|
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
|
||||||
if client_config["master_password_hash"] == master_password_hash:
|
if client_config["master_password_hash"] == master_password_hash:
|
||||||
print("マスターパスワードで認証しました。")
|
print(f'{lang["Lock"]["auth"]["print"]["success_master_password"]}')
|
||||||
self.exit()
|
self.exit()
|
||||||
else:
|
else:
|
||||||
print("マスターパスワードで認証できませんでした。")
|
print(f'{lang["Lock"]["auth"]["print"]["error_master_password"]}')
|
||||||
self.withdraw()
|
self.withdraw()
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | ネットワークエラー", message=f"認証サーバーにアクセスできませんでした。\n続行するには、マスターパスワードを入力してください。")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["cant_access_auth_server"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["cant_access_auth_server"]["details"]}")
|
||||||
self.msg_subtitle_1.configure(text='ネットワークエラーが発生しています。\n続行するには、マスターパスワードを入力して下さい。 ')
|
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["cant_access_auth_server"]}')
|
||||||
self.button_enable()
|
self.button_enable()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
|
|
||||||
|
@ -474,7 +484,7 @@ class Lock(customtkinter.CTkToplevel):
|
||||||
|
|
||||||
def help_dummy(self):
|
def help_dummy(self):
|
||||||
self.withdraw()
|
self.withdraw()
|
||||||
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
|
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["help"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["help"]["details"]}")
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
|
|
||||||
def wakeup_shutdown_background(self):
|
def wakeup_shutdown_background(self):
|
||||||
|
@ -511,106 +521,10 @@ class Help(customtkinter.CTkToplevel):
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
|
||||||
class Stop():
|
|
||||||
def __init__(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
stop_thread = threading.Thread(target=self.stop)
|
|
||||||
stop_thread.run()
|
|
||||||
|
|
||||||
def delete_appdata(self, **kwargs):
|
|
||||||
process_name = kwargs["process_name"]
|
|
||||||
dir_path = kwargs["dir_path"]
|
|
||||||
|
|
||||||
if not os.path.exists(dir_path):
|
|
||||||
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
i_max = 10
|
|
||||||
result = 1
|
|
||||||
while i != i_max:
|
|
||||||
i += 1
|
|
||||||
try:
|
|
||||||
# プロセスの終了
|
|
||||||
subprocess.run(f'taskkill /f /t /im {process_name}', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
|
|
||||||
print(f"{process_name} を終了しました。")
|
|
||||||
time.sleep(0.1)
|
|
||||||
# ディレクトリの削除
|
|
||||||
shutil.rmtree(dir_path)
|
|
||||||
if os.path.isdir(dir_path):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
print(f"{dir_path} を削除しました。")
|
|
||||||
result = 0
|
|
||||||
i = i_max
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"プロセス終了エラー: {e}")
|
|
||||||
|
|
||||||
except PermissionError as e:
|
|
||||||
print(f"権限エラー: {e}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print("エラーが発生しました。\nエラー内容:")
|
|
||||||
print(f"エラータイプ: {e.__class__.__name__}")
|
|
||||||
print(f"エラー引数: {e.args}")
|
|
||||||
print(f"エラーメッセージ: {str(e)}")
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
shutdown_command = subprocess.run('shutdown /s /f /t 0', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
print("停止処理を実行。")
|
|
||||||
if client_config["eraser"] == True:
|
|
||||||
appdata_local = os.path.expandvars("%LOCALAPPDATA%")
|
|
||||||
appdata_roaming = os.path.expandvars("%APPDATA%")
|
|
||||||
epic_del = self.delete_appdata(process_name="EpicGamesLauncher.exe", dir_path=f"{appdata_local}\\EpicGamesLauncher\\Saved")
|
|
||||||
chrome_del = self.delete_appdata(process_name="chrome.exe", dir_path=f"{appdata_local}\\Google\\Chrome\\User Data")
|
|
||||||
discord_del = self.delete_appdata(process_name="discord.exe", dir_path=f"{appdata_roaming}\\discord")
|
|
||||||
steam_del = self.delete_appdata(process_name="steam.exe", dir_path=f"{appdata_local}\\Steam")
|
|
||||||
ea_del = self.delete_appdata(process_name="EADesktop.exe", dir_path=f"{appdata_local}\\Electronic Arts")
|
|
||||||
riot_del = self.delete_appdata(process_name="RiotClientServices.exe", dir_path=f"{appdata_local}\\Riot Games\\Riot Client")
|
|
||||||
else:
|
|
||||||
print("削除処理をスキップ。")
|
|
||||||
stop_url = client_config["auth_host_url"] + "/stop"
|
|
||||||
stop_json = {
|
|
||||||
"pc_number": int(client_config["pc_number"]),
|
|
||||||
"pc_uuid": str(client_config["pc_uuid"]),
|
|
||||||
"pc_token": str(client_config["pc_token"])
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
responce = requests.post(stop_url, json=stop_json)
|
|
||||||
if responce.status_code == 200:
|
|
||||||
print("停止処理は成功しました。")
|
|
||||||
elif responce.status_code == 401:
|
|
||||||
print("認証に失敗しました。")
|
|
||||||
else:
|
|
||||||
print("内部エラーにより停止処理に失敗しました。")
|
|
||||||
except:
|
|
||||||
print("ネットワークエラーにより停止処理に失敗しました。")
|
|
||||||
finally:
|
|
||||||
self.shutdown()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = sys.argv
|
args = sys.argv
|
||||||
if len(args) >= 2:
|
if len(args) >= 2:
|
||||||
if args[1] == "stop":
|
if args[1] == "setup":
|
||||||
init_result = init()
|
|
||||||
if init_result == 1:
|
|
||||||
print("多重起動を検出。")
|
|
||||||
elif init_result == 2:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
stop = Stop()
|
|
||||||
stop.run()
|
|
||||||
|
|
||||||
elif args[1] == "setup":
|
|
||||||
if len(args) == 4:
|
if len(args) == 4:
|
||||||
init_result = init(pc_number=args[2], onetime=args[3])
|
init_result = init(pc_number=args[2], onetime=args[3])
|
||||||
elif len(args) == 5:
|
elif len(args) == 5:
|
||||||
|
|
105
lang/lang_client.json
Normal file
105
lang/lang_client.json
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
{
|
||||||
|
"ja": {
|
||||||
|
"init": {
|
||||||
|
"print": {
|
||||||
|
"init_ok": "PCの情報が登録されました。"
|
||||||
|
},
|
||||||
|
"msgbox": {
|
||||||
|
"not_found_pc_number": {
|
||||||
|
"title": "登録時にエラー",
|
||||||
|
"details": "登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。"
|
||||||
|
},
|
||||||
|
"not_found_onetime_password": {
|
||||||
|
"title": "登録時にエラー",
|
||||||
|
"details": "登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。"
|
||||||
|
},
|
||||||
|
"init_ok": {
|
||||||
|
"title": "初回起動を検出",
|
||||||
|
"details": "初回起動のようです。\nマスターパスワードを記録しておいてください。\nBotが起動している場合は、管理者がDiscordから確認することもできます。"
|
||||||
|
},
|
||||||
|
"exist_pc_number": {
|
||||||
|
"title": "登録時にエラー",
|
||||||
|
"details": "登録時にエラーが発生しました。\n指定されたPC番号には既に登録されています。PCを置き換えたい場合は、Botから登録を解除してください。"
|
||||||
|
},
|
||||||
|
"wrong_onetime_password": {
|
||||||
|
"title": "登録時にエラー",
|
||||||
|
"details": "登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。"
|
||||||
|
},
|
||||||
|
"internal_error": {
|
||||||
|
"title": "登録時にエラー",
|
||||||
|
"details": "登録時にエラーが発生しました。\nサーバーで内部エラーが発生しています。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"App": {
|
||||||
|
"title": "ロック中",
|
||||||
|
"msgbox": {
|
||||||
|
"init_error": {
|
||||||
|
"title": "初回処理のエラー",
|
||||||
|
"message": "初回処理の実行にエラーが発生しました。\n自動的にサインアウトされます。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"success": {
|
||||||
|
"title": "ご協力ありがとうございます!",
|
||||||
|
"details": "パスワード認証に成功しました。\n現在使われたパスワードは削除されます。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"Lock": {
|
||||||
|
"gui": {
|
||||||
|
"locked": "ロックされています",
|
||||||
|
"pc_number": "PC番号",
|
||||||
|
"testing": "テストモード",
|
||||||
|
"pc_number_title_1": "PC番号",
|
||||||
|
"msg_title_1": "ちょっと待って!! ",
|
||||||
|
"msg_title_2": "本当にあなたですか?",
|
||||||
|
"msg_subtitle_1": "サインインするには、Discordを開き、Dislockerから送信された\nパスワードを入力してください。",
|
||||||
|
"msg_subtitle_2": "※ パスワードの有効期限は発行から5分間です。期限が切れた場合は、もう一度発行してください。",
|
||||||
|
"password_entry": "パスワード",
|
||||||
|
"signin_button": "サインイン",
|
||||||
|
"signout_button": "サインアウト",
|
||||||
|
"help_button": "ヘルプ"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"print": {
|
||||||
|
"try_master_password": "マスターパスワードで認証を試行します。",
|
||||||
|
"success_master_password": "マスターパスワードで認証しました。",
|
||||||
|
"error_master_password": "マスターパスワードで認証できませんでした。",
|
||||||
|
"access_auth_server": "認証サーバーにアクセスします。",
|
||||||
|
"success_auth_server": "認証サーバー経由で認証しました。",
|
||||||
|
"error_wrong_password": "パスワードが間違っているため認証に失敗しました。",
|
||||||
|
"error_internal_server": "サーバーで内部エラーが発生しています。",
|
||||||
|
"cant_access_auth_server": "認証サーバーにアクセスできません。マスターパスワードで認証を試行します。"
|
||||||
|
},
|
||||||
|
"msgbox": {
|
||||||
|
"wrong_password": {
|
||||||
|
"title": "誤ったパスワード",
|
||||||
|
"details": "パスワードが間違っています!\n\nヒント\nパスワード発行から時間が経っていますか?もう一度パスワードが発行できるか試してみてください。"
|
||||||
|
},
|
||||||
|
"internal_error": {
|
||||||
|
"title": "内部エラー",
|
||||||
|
"details": "サーバーの内部エラーにより認証に失敗しました。\n管理者にお問い合わせください。"
|
||||||
|
},
|
||||||
|
"cant_access_auth_server": {
|
||||||
|
"title": "アクセスエラー",
|
||||||
|
"details": "認証サーバーに接続できませんでした。\n続行するには、マスターパスワードを入力してください。"
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
"title": "ヘルプ",
|
||||||
|
"details": "ヘルプページは制作途中です。\n詳しくは、Discordのサーバーのチュートリアルをご覧ください。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configure": {
|
||||||
|
"wrong_password": "パスワードが間違っています! ",
|
||||||
|
"internal_error": "内部エラーにより認証に失敗しました。 ",
|
||||||
|
"cant_access_auth_server": "認証サーバーに接続できません。\n続行するには、マスターパスワードを入力して下さい。 "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,3 +3,4 @@ winotify
|
||||||
keyboard
|
keyboard
|
||||||
requests
|
requests
|
||||||
pywin32
|
pywin32
|
||||||
|
pillow
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
31
resource/css/admin.css
Normal file
31
resource/css/admin.css
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#sidebar {
|
||||||
|
height: 100%;
|
||||||
|
width: 30%;
|
||||||
|
background-color: aliceblue;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#general {
|
||||||
|
display: flex;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pc_list_table {
|
||||||
|
width: 50%;
|
||||||
|
table-layout: fixed;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 2px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 2px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 2px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 8px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 2px solid;
|
||||||
|
}
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
@ -8,14 +8,6 @@ if %ERRORLEVEL% == 0 (
|
||||||
if %ERRORLEVEL% == 1 (
|
if %ERRORLEVEL% == 1 (
|
||||||
echo タスクスケジューラーの設定でエラーが発生しました。
|
echo タスクスケジューラーの設定でエラーが発生しました。
|
||||||
)
|
)
|
||||||
Cscript "%dir%shortcut.vbs" "%dir%" "%dir%" "dislocker_client.exe" "stop" "シャットダウンと停止処理"
|
|
||||||
if %ERRORLEVEL% == 0 (
|
|
||||||
Cscript "%dir%shortcut.vbs" "%USERPROFILE%/Desktop" "%dir%" "dislocker_client.exe" "stop" "シャットダウンと停止処理"
|
|
||||||
echo ショートカットの作成は完了しました。
|
|
||||||
)
|
|
||||||
if %ERRORLEVEL% == 1 (
|
|
||||||
echo ショートカットの作成でエラーが発生しました。
|
|
||||||
)
|
|
||||||
|
|
||||||
set /P pc_number=PC番号を入力
|
set /P pc_number=PC番号を入力
|
||||||
set /P onetime=ワンタイムパスワードを入力
|
set /P onetime=ワンタイムパスワードを入力
|
||||||
|
|
24
templates/admin.html
Normal file
24
templates/admin.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Dislocker Admin</title>
|
||||||
|
<link rel="stylesheet" href="{{url_for('static', filename='/css/admin.css')}}">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="general">
|
||||||
|
<div id="sidebar">
|
||||||
|
<button onclick="location.href='/admin'" type="button" style="height: auto;" >
|
||||||
|
<img src="{{url_for('static', filename='/icon/png/64.png')}}" alt="Home" style="width: 64px; height: 64px;">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
<h1>Dislocker ADMIN</h1>
|
||||||
|
<button onclick="location.href='/admin/pc_list'">PCリスト</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
25
templates/pc_list.html
Normal file
25
templates/pc_list.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Dislocker Admin | PC List</title>
|
||||||
|
<link rel="stylesheet" href="{{url_for('static', filename='/css/admin.css')}}">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="general">
|
||||||
|
<div id="sidebar">
|
||||||
|
<button onclick="location.href='/admin'" type="button" style="height: auto;">
|
||||||
|
<img src="{{url_for('static', filename='/icon/png/64.png')}}" alt="Home" style="width: 64px; height: 64px;">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
<h1>PCリストあるよ(笑)</h1>
|
||||||
|
<h2>登録されたPCのみが表示されています。</h2>
|
||||||
|
{{pc_list_table | safe}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue