misc: move gateway path
This commit is contained in:
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
interface Window {
|
||||
pathConfig: {
|
||||
root: string,
|
||||
sharedIcon: string,
|
||||
gameImage: string,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
import axios from 'axios';
|
||||
import $ from 'jquery';
|
||||
import { isNumber } from 'lodash';
|
||||
import { TemplateEngine } from '../util/TemplateEngine';
|
||||
import { InvalidResponse } from '../defs';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { unwrap_any } from '../util/unwrap_any';
|
||||
import { convertFormData } from '../util/convertFormData';
|
||||
import { exportWindow } from '../util/exportWindow';
|
||||
|
||||
type UserEntry = {
|
||||
userID: string,
|
||||
userName: string,
|
||||
email: string,
|
||||
authType: string | null,
|
||||
userGrade: number,
|
||||
blockUntil: string | null,
|
||||
nickname: string,
|
||||
icon: string,
|
||||
joinDate: string,
|
||||
loginDate: string,
|
||||
deleteAfter: string | null,
|
||||
}
|
||||
|
||||
type UserListResponse = {
|
||||
result: true,
|
||||
users: UserEntry[],
|
||||
servers: string[],
|
||||
allowJoin: boolean,
|
||||
allowLogin: boolean,
|
||||
}
|
||||
|
||||
const userFrame = '\
|
||||
<tr id="userinfo_<%userID%>" data-username="<%userName%>" data-id="<%userID%>">\
|
||||
<th scope="row"><%userID%></th>\
|
||||
<td><%userName%></td>\
|
||||
<td class="small"><%emailFunc(email)%><br>(<%authType%>)</td>\
|
||||
<td><%userGradeText%><p class="small hide_text user_grade_<%userGrade%>" style="margin:0;"><%shortDate(blockUntil)%></p></td>\
|
||||
<td><%nickname%></td>\
|
||||
<td><img class="generalIcon" src="<%icon%>" width="64" height="64"></td>\
|
||||
<td class="small"><%slotGeneralList%></td>\
|
||||
<td class="small"><%shortDate(joinDate)%></td>\
|
||||
<td class="small"><%shortDate(loginDate)%></td>\
|
||||
<td class="small"><%shortDate(deleteAfter)%></td>\
|
||||
<td>\
|
||||
<div class="btn-group" role="group">\
|
||||
<button type="button" onclick="changeUserStatus(\'delete\', this);" class="btn btn-danger btn-sm">강제<br>탈퇴</button>\
|
||||
<button type="button" onclick="changeUserStatus(\'reset_pw\', this);" class="btn btn-info btn-sm">암호<br>변경</button>\
|
||||
<button type="button" onclick="changeUserStatus(\'block\', this);" class="btn btn-warning btn-sm">유저<br>차단</button>\
|
||||
<button type="button" onclick="changeUserStatus(\'unblock\', this);" class="btn btn-secondary btn-sm">차단<br>해제</button>\
|
||||
<button type="button" onclick="changeUserStatus(\'set_userlevel\', this);" class="btn btn-primary btn-sm">별도<br>권한</button>\
|
||||
</div>\
|
||||
</td>\
|
||||
</tr>';
|
||||
|
||||
function convUserGrade(grade: number): string {
|
||||
const userGradeMap = {
|
||||
0: '차단',
|
||||
1: '일반',
|
||||
4: '특별',
|
||||
5: '부운영자',
|
||||
6: '운영자'
|
||||
};
|
||||
|
||||
if (grade in userGradeMap) {
|
||||
return userGradeMap[grade as (keyof typeof userGradeMap)];
|
||||
}
|
||||
return grade.toString();
|
||||
}
|
||||
|
||||
function fillAllowJoinLogin(result: UserListResponse) {
|
||||
if (result.allowJoin) {
|
||||
$('#allow_join_y').trigger('click');
|
||||
}
|
||||
else {
|
||||
$('#allow_join_n').trigger('click');
|
||||
}
|
||||
|
||||
if (result.allowLogin) {
|
||||
$('#allow_login_y').trigger('click');
|
||||
}
|
||||
else {
|
||||
$('#allow_login_n').trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
function fillUserList(result: UserListResponse) {
|
||||
const $user_list = $('#user_list');
|
||||
|
||||
|
||||
$user_list.empty();
|
||||
|
||||
const slotGeneralList = $.map(result.servers, function (value) {
|
||||
return `<span class="server_generalName_${value}"></span>`;
|
||||
}).join('<br>');
|
||||
|
||||
const emailFunc = function (text: string) {
|
||||
return String(text).replace('@', '@<br>');
|
||||
}
|
||||
const brFunc = function (text: string) {
|
||||
return String(text).split(' ').join('<br>');
|
||||
};
|
||||
|
||||
const shortDateFunc = function (date: string | null) {
|
||||
if (!date) {
|
||||
return '-';
|
||||
}
|
||||
return brFunc(date.substr(2));
|
||||
}
|
||||
|
||||
$.each(result.users, function (idx, user) {
|
||||
const templateItem = {
|
||||
...user,
|
||||
email: user.email ?? '-',
|
||||
br: brFunc,
|
||||
shortDate: shortDateFunc,
|
||||
emailFunc: emailFunc,
|
||||
slotGeneralList: slotGeneralList,
|
||||
userGradeText: convUserGrade(user.userGrade),
|
||||
}
|
||||
|
||||
$user_list.append(
|
||||
TemplateEngine(userFrame, templateItem)
|
||||
)
|
||||
});
|
||||
|
||||
//TODO: slotGeneralList에 값을 채워야함. ajax로 받아올 필요 있음
|
||||
}
|
||||
|
||||
async function changeSystem(action: string, param?: string): Promise<void> {
|
||||
const text = `${action}${param ? (', ' + param) : ''}을 진행합니다.`;
|
||||
if (!confirm(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | {
|
||||
result: true,
|
||||
affected?: number,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_set_userlist.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
'action': action,
|
||||
'param': param ?? null
|
||||
})
|
||||
})
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.affected) {
|
||||
alert(`${result.affected}건이 처리되었습니다.`);
|
||||
await refreshAll();
|
||||
}
|
||||
else {
|
||||
alert('완료되었습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
async function changeUserStatus(action: string, userID: Element | number, param?: number): Promise<void> {
|
||||
if (userID instanceof Element) {
|
||||
userID = parseInt($(userID).parents('tr').data('id'));
|
||||
}
|
||||
if (!isNumber(userID)) {
|
||||
alert('userID가 올바르게 지정되지 않았습니다!');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (action == 'set_userlevel') {
|
||||
if (!isNumber(param)) {
|
||||
param = parseInt(prompt('원하는 등급을 입력해주세요.(1:일반, 4:특별, 5:부운영자, 6:운영자)', '1') ?? '0');
|
||||
}
|
||||
|
||||
if (param < 1 || param > 6) {
|
||||
alert('올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == 'block') {
|
||||
if (!isNumber(param)) {
|
||||
param = parseInt(prompt('블록 기간을 입력해주세요. <= 0은 반영구(50년)입니다.', '7') ?? '7');
|
||||
}
|
||||
}
|
||||
|
||||
const userName = unwrap_any<string>($('#userinfo_' + userID).data('username'));
|
||||
|
||||
const text = `${userName}에 대해서 ${action}${param ? (', ' + param) : ''}을 진행합니다.`;
|
||||
if (!confirm(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | {
|
||||
result: true,
|
||||
detail?: string,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_set_userlist.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
'action': action,
|
||||
'user_id': userID,
|
||||
'param': param ?? null
|
||||
})
|
||||
})
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.detail) {
|
||||
alert(`완료되었습니다: ${result.detail}`);
|
||||
}
|
||||
else {
|
||||
alert('완료되었습니다.');
|
||||
}
|
||||
|
||||
await refreshAll();
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
let result: InvalidResponse | UserListResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_get_userlist.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
fillAllowJoinLogin(result);
|
||||
fillUserList(result);
|
||||
}
|
||||
|
||||
$(async function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
await refreshAll();
|
||||
|
||||
$('input[name=allow_join], input[name=allow_login]').on('change', async function () {
|
||||
const $this = $(this);
|
||||
await changeSystem(unwrap_any<string>($this.attr('name')), unwrap_any<string>($this.val()));
|
||||
})
|
||||
});
|
||||
|
||||
exportWindow(changeSystem, 'changeSystem');
|
||||
exportWindow(changeUserStatus, 'changeUserStatus');
|
||||
@@ -0,0 +1,332 @@
|
||||
|
||||
import $ from 'jquery';
|
||||
import axios from 'axios';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { InvalidResponse } from '../defs';
|
||||
import { convertFormData } from '../util/convertFormData';
|
||||
import { TemplateEngine } from "../util/TemplateEngine";
|
||||
import { unwrap_any } from '../util/unwrap_any';
|
||||
import { unwrap } from '../util/unwrap';
|
||||
|
||||
type ServerUpdateResponse = {
|
||||
result: true,
|
||||
version: string,
|
||||
server: string,
|
||||
imgResult: false,
|
||||
}
|
||||
|
||||
type ServerRootUpdateResponse = {
|
||||
result: true,
|
||||
version: string,
|
||||
server: string,
|
||||
imgResult: true,
|
||||
imgDetail: string,
|
||||
}
|
||||
|
||||
type ServerStateItem = {
|
||||
name: string,
|
||||
korName: string,
|
||||
color: string,
|
||||
isRoot: boolean,
|
||||
lastGitPath: string,
|
||||
valid: boolean,
|
||||
run: boolean,
|
||||
installed: boolean,
|
||||
version: string,
|
||||
reason: string,
|
||||
status?: string,
|
||||
}
|
||||
|
||||
type ServerStateResponse = {
|
||||
acl: Record<string, string[]>,
|
||||
server: ServerStateItem[],
|
||||
grade: number,
|
||||
}
|
||||
|
||||
type ServerChangeResponse = {
|
||||
result: true,
|
||||
installURL?: string,
|
||||
}
|
||||
|
||||
const serverAdminTemplate = '\
|
||||
<tr class="bg0 server_admin_<%name%>" data-server_name="<%name%>" data-is_root="<%isRoot%>" data-git-path="<%lastGitPath%>">\
|
||||
<th style="color:<%color%>;"><%korName%>(<%name%>)</th>\
|
||||
<td><%status%></td>\
|
||||
<td><%version%></td>\
|
||||
<td><button type="button" class="serv_act_close with_skin valid_if_set with_border obj_fill" onclick="modifyServerStatus(this, \'close\');">폐쇄</button></td>\
|
||||
<td><button type="button" class="serv_act_open with_skin valid_if_set with_border obj_fill" onclick="modifyServerStatus(this, \'open\');">오픈</button></td>\
|
||||
<td><a class="just_link" href="../<%name%>/install.php"><button type="button" class="serv_act_reset with_skin valid_if_set with_border obj_fill">리셋</button></a></td>\
|
||||
<td><a class="just_link" href="../<%name%>/install_db.php"><button type="button" class="serv_act_hard_reset with_skin valid_if_installed only_admin with_border obj_fill">하드리셋</button></a></td>\
|
||||
<td><button type="button" class="serv_act_login_close with_skin valid_if_set with_border obj_fill" onclick="Entrance_AdminClosedLogin(this);">폐쇄중 로그인</button></td>\
|
||||
<td><button type="button" class="serv_act_119 with_skin valid_if_set with_border obj_fill" onclick="Entrance_AdminOpen119(this);">서버119</button></td>\
|
||||
<td><button type="button" class="serv_act_update with_skin with_border obj_fill" onclick="serverUpdate(this);">업데이트</button></td>\
|
||||
</tr>\
|
||||
';//TODO: npm install 관련 기능 추가, js/css output 경로 변경
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
modifyServerStatus: (caller: HTMLElement, action: string) => void;
|
||||
Entrance_AdminClosedLogin: (caller: HTMLElement) => void;
|
||||
Entrance_AdminOpen119: (caller: HTMLElement) => void;
|
||||
serverUpdate: (caller: HTMLElement) => void;
|
||||
adminGrade: number;
|
||||
aclList: Record<string, string[]>;
|
||||
}
|
||||
}
|
||||
|
||||
async function serverUpdate(caller: HTMLElement) {
|
||||
const $caller = $(caller);
|
||||
const $tr = $caller.parents('tr');
|
||||
const server = unwrap_any<string>($tr.data('server_name'));
|
||||
let isRoot: string | boolean = unwrap_any<string>($tr.data('is_root'));
|
||||
|
||||
let target = $tr.data('gitPath');
|
||||
|
||||
if (typeof isRoot !== 'boolean') {
|
||||
isRoot = (isRoot != 'false');
|
||||
}
|
||||
|
||||
let allowFullUpdate = (server in window.aclList && window.aclList[server].indexOf('fullUpdate') >= 0);
|
||||
allowFullUpdate = allowFullUpdate || window.adminGrade > 5;
|
||||
|
||||
let allowUpdate = (server in window.aclList && window.aclList[server].indexOf('update') >= 0);
|
||||
allowUpdate = allowUpdate || window.adminGrade >= 5;
|
||||
allowUpdate = allowUpdate || allowFullUpdate;
|
||||
|
||||
if (!allowUpdate) {
|
||||
alert('권한이 없습니다!');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (allowFullUpdate) {
|
||||
target = prompt('가져올 git tree-ish 명을 입력해주세요.', target)
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isRoot) {
|
||||
if (!confirm('서버 라이브러리, 루트 서버에 대해 git pull을 실행합니다.')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!confirm('다음 git tree-ish 주소로 업데이트를 시도합니다 : ' + target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | ServerUpdateResponse | ServerRootUpdateResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: '../j_updateServer.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
server: server,
|
||||
target: target
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`에러: ${e}`);
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(`실패했습니다: ${result.reason}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let aux = '';
|
||||
if (result.imgResult) {
|
||||
aux = ` (이미지 서버 갱신:${result.imgResult}, ${result.imgDetail})`;
|
||||
}
|
||||
alert(`${result.server} 서버가 ${result.version} 버전으로 업데이트 되었습니다.${aux}`);
|
||||
}
|
||||
|
||||
function drawServerAdminList(serverList: ServerStateResponse) {
|
||||
const $table = $('#server_admin_list');
|
||||
const $showErrorLog = $('#showErrorLog');
|
||||
|
||||
if (serverList.grade >= 5) {
|
||||
$showErrorLog.show();
|
||||
}
|
||||
$.each(serverList.server, function (idx, server) {
|
||||
console.log(server);
|
||||
let status: string;
|
||||
if (!server.valid) {
|
||||
status = `에러, ${server.reason}`;
|
||||
}
|
||||
else if (!server.run) {
|
||||
status = '폐쇄됨';
|
||||
}
|
||||
else {
|
||||
status = '운영 중';
|
||||
}
|
||||
server.status = status;
|
||||
|
||||
const $tr = $(TemplateEngine(serverAdminTemplate, server));
|
||||
$table.append($tr);
|
||||
if (serverList.grade < 4) {
|
||||
$tr.find('button').prop('disabled', true);
|
||||
}
|
||||
if (!server.valid) {
|
||||
$tr.find('.valid_if_set').prop('disabled', true);
|
||||
}
|
||||
if (!server.installed) {
|
||||
$tr.find('.valid_if_installed').prop('disabled', true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const aclByServer = serverList.acl[server.name];
|
||||
|
||||
$.each(aclByServer, function (idx, action) {
|
||||
console.log(action);
|
||||
if (action == 'update' || action == 'fullUpdate') {
|
||||
if (!server.installed) {
|
||||
return true;
|
||||
}
|
||||
$tr.find('.serv_act_update').prop('disabled', false);
|
||||
$showErrorLog.show();
|
||||
}
|
||||
else if (action == 'openClose') {
|
||||
if (!server.valid) {
|
||||
return true;
|
||||
}
|
||||
$tr.find('.serv_act_open, .serv_act_close').prop('disabled', false);
|
||||
}
|
||||
else if (action == 'reset') {
|
||||
if (!server.installed) {
|
||||
return true;
|
||||
}
|
||||
$tr.find('.serv_act_reset, .serv_act_close').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
window.adminGrade = serverList.grade;
|
||||
window.aclList = serverList.acl;
|
||||
if (serverList.grade <= 5) {
|
||||
$table.find('.only_admin').prop('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadPlugin(): Promise<void> {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
Entrance_AdminInit();
|
||||
|
||||
window.modifyServerStatus = modifyServerStatus;
|
||||
window.Entrance_AdminClosedLogin = Entrance_AdminClosedLogin;
|
||||
window.Entrance_AdminOpen119 = Entrance_AdminOpen119;
|
||||
window.serverUpdate = serverUpdate;
|
||||
|
||||
const response = await axios({
|
||||
url: 'j_server_get_admin_status.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
});
|
||||
|
||||
drawServerAdminList(response.data);
|
||||
}
|
||||
|
||||
function Entrance_AdminInit() {
|
||||
console.log('adminInit');
|
||||
$("#Entrance_000202").on('click', Entrance_Member);
|
||||
$("#notice_change_btn").on('click', Entrance_AdminChangeNotice);
|
||||
}
|
||||
|
||||
function Entrance_Member(e: JQuery.Event) {
|
||||
e.preventDefault();
|
||||
$("#Entrance_00").hide();
|
||||
$("#EntranceMember_00").show();
|
||||
}
|
||||
|
||||
async function Entrance_AdminChangeNotice(e: JQuery.Event) {
|
||||
e.preventDefault();
|
||||
const notice = unwrap_any<string>($("#notice_edit").val());
|
||||
|
||||
if (!confirm('정말 실행하시겠습니까?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | ServerChangeResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_server_change_status.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
action: 'notice',
|
||||
notice: notice
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(`실패했습니다: ${result.reason}`);
|
||||
return;
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
|
||||
async function modifyServerStatus(caller: HTMLElement, action: string) {
|
||||
const $caller = $(caller);
|
||||
const server = unwrap_any<string>($caller.parents('tr').data('server_name'));
|
||||
|
||||
if (!confirm('정말 실행하시겠습니까?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | ServerChangeResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_server_change_status.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
server: server,
|
||||
action: action
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(`실패했습니다: ${result.reason}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == 'reset') {
|
||||
location.href = unwrap(result.installURL);
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
function Entrance_AdminClosedLogin(caller: HTMLElement) {
|
||||
const $caller = $(caller);
|
||||
const serverDir = $caller.parents('tr').data('server_name');
|
||||
location.href = serverDir + "/npc_login.php";
|
||||
}
|
||||
|
||||
function Entrance_AdminOpen119(caller: HTMLElement) {
|
||||
const $caller = $(caller);
|
||||
const serverDir = $caller.parents('tr').data('server_name');
|
||||
location.href = `../${serverDir}/_119.php`;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from '../common_deprecated';
|
||||
@@ -0,0 +1,312 @@
|
||||
import axios from 'axios';
|
||||
import $ from 'jquery';
|
||||
import { initTooltip } from '../common_legacy';
|
||||
import { TemplateEngine } from "../util/TemplateEngine";
|
||||
import { InvalidResponse } from '../defs';
|
||||
import { getDateTimeNow } from '../util/getDateTimeNow';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { loadPlugin as loadAdminPlugin } from './admin_server';
|
||||
|
||||
declare const isAdmin: boolean;
|
||||
|
||||
const serverListTemplate = "\
|
||||
<tr class='server_item bg0 server_name_<%name%>' data-server='<%name%>'>\
|
||||
<td class='server_name obj_tooltip' data-toggle='tooltip' data-placement='bottom'>\
|
||||
<span style='font-weight:bold;font-size:1.4em;color:<%color%>'><%korName%>섭</span><br>\
|
||||
<span class='n_country'></span>\
|
||||
<span class='tooltiptext server_date'></span>\
|
||||
</td>\
|
||||
<td colspan='4' class='server_down'>- 폐 쇄 중 -</td>\
|
||||
</tr>\
|
||||
";
|
||||
|
||||
const serverTextInfo = "\
|
||||
<td>\
|
||||
서기 <%year%>년 <%month%>월 (<span style='color:orange;'><%scenario%></span>)<br>\
|
||||
유저 : <%userCnt%> / <%maxUserCnt%>명 <span style='color:cyan;'>NPC : <%npcCnt%>명</span> (<span style='color:limegreen;'><%turnTerm%>분 턴 서버</span>)<br>\
|
||||
(상성 설정:<%fictionMode%>), (기타 설정:<%otherTextInfo%>)\
|
||||
</td>\
|
||||
";
|
||||
|
||||
const serverProvisionalInfo = "\
|
||||
<td>\
|
||||
- 오픈 일시 : <%opentime%> -<br>\
|
||||
서기 <%year%>년 <%month%>월 (<span style='color:orange;'><%scenario%></span>)<br>\
|
||||
유저 : <%userCnt%> / <%maxUserCnt%>명 <span style='color:cyan;'>NPC : <%npcCnt%>명</span> (<span style='color:limegreen;'><%turnTerm%>분 턴 서버</span>)<br>\
|
||||
(상성 설정:<%fictionMode%>), (기타 설정:<%otherTextInfo%>)\
|
||||
</td>\
|
||||
";
|
||||
|
||||
const serverFullTemplate = "\
|
||||
<td colspan='4' class='server_full'>- 장수 등록 마감 -</td>\
|
||||
";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverSelectPoolTemplate = "\
|
||||
<td colspan='2' class='not_registered'>- 미 등 록 -</td>\
|
||||
<td class='ignore_border'>\
|
||||
<a href='<%serverPath%>/select_general_from_pool.php'><button type='button' class='general_select with_skin'>장수선택</button></a>\
|
||||
</td>\
|
||||
";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverLoginBtn = "<a href='<%serverPath%>/' class='item'\
|
||||
><button type='button' class='fill_box with_skin'>입장</button\
|
||||
></a>";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverCreateBtn = "<a href='<%serverPath%>/join.php' class='item'\
|
||||
><button type='button' class='fill_box with_skin'>장수생성</button\
|
||||
></a>";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverSelectNPCBtn = "<a href='<%serverPath%>/select_npc.php' class='item'\
|
||||
><button type='button' class='fill_box with_skin'>장수빙의</button\
|
||||
></a>";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverSelectPoolBtn = "<a href='<%serverPath%>/select_general_from_pool.php' class='item'\
|
||||
><button type='button' class='fill_box with_skin'>장수선택</button\
|
||||
></a>";
|
||||
|
||||
const serverCreateTemplate = "\
|
||||
<td colspan='2' class='not_registered'>- 미 등 록 -</div>\
|
||||
<td class='ignore_border vertical_flex BtnPlate'>\
|
||||
<%if(canCreate) {%>\
|
||||
<a href='<%serverPath%>/join.php' class='item'><button type='button' class='fill_box with_skin'>장수생성</button></a>\
|
||||
<%}%>\
|
||||
<%if(canSelectNPC) {%>\
|
||||
<a href='<%serverPath%>/select_npc.php' class='item'><button type='button' class='fill_box with_skin'>장수빙의</button></a>\
|
||||
<%}%>\
|
||||
<%if(canSelectPool) {%>\
|
||||
<a href='<%serverPath%>/select_general_from_pool.php' class='item'><button type='button' class='fill_box with_skin'>장수선택</button></a>\
|
||||
<%}%>\
|
||||
</td>";
|
||||
|
||||
const serverLoginTemplate = "\
|
||||
<td style='background:url(\"<%picture%>\");background-size: 64px 64px;'></td>\
|
||||
<td><%name%></td>\
|
||||
<td class='ignore_border vertical_flex BtnPlate'>\
|
||||
<a href='<%serverPath%>/' class='item'><button type='button' class='fill_box with_skin'>입장</button></a>\
|
||||
</td>\
|
||||
";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const serverReservedTemplate = "\
|
||||
<td colspan='4' class='server_reserved'>\
|
||||
<%openDatetime==starttime?'':'- 가오픈 일시 : '+openDatetime+ '- <br>'%>\
|
||||
- 오픈 일시 : <%starttime%> - <br>\
|
||||
<span style='color:orange;'><%scenarioName%></span> <span style='color:limegreen;'><%turnterm%>분 턴 서버</span><br>\
|
||||
(상성 설정:<%fictionMode%>), (빙의 여부:<%npcMode%>), (최대 스탯:<%gameConf.defaultStatTotal%>), (기타 설정:<%otherTextInfo%>)\
|
||||
</td>\
|
||||
";
|
||||
|
||||
type ServerResponseItem = {
|
||||
color: string,
|
||||
korName: string,
|
||||
name: string,
|
||||
exists: boolean,
|
||||
enable: boolean,
|
||||
};
|
||||
|
||||
type ServerResponse = {
|
||||
result: true;
|
||||
reason: 'success';
|
||||
server: ServerResponseItem[];
|
||||
}
|
||||
|
||||
type RawServerResponse = InvalidResponse | ServerResponse;
|
||||
|
||||
type ReservedGameInfo = {
|
||||
scenarioName: string,
|
||||
turnterm: number,
|
||||
fictionMode: '가상' | '사실',
|
||||
block_general_create: boolean,
|
||||
npcMode: '불가' | '가능' | '선택 생성',
|
||||
openDatetime: string,
|
||||
starttime: string,
|
||||
gameConf: Record<string, string | number>,
|
||||
otherTextInfo: string,
|
||||
}
|
||||
|
||||
type GameInfo = {
|
||||
isUnited: number,
|
||||
npcMode: '불가' | '가능' | '선택 생성',
|
||||
year: number,
|
||||
month: number,
|
||||
scenario: string,
|
||||
maxUserCnt: number,
|
||||
turnTerm: number,
|
||||
opentime: string,
|
||||
starttime: string,
|
||||
turntime: string,
|
||||
join_mode: string,
|
||||
fictionMode: '가상' | '사실',
|
||||
block_general_create: boolean,
|
||||
autorun_user: string,
|
||||
userCnt: number,
|
||||
npcCnt: number,
|
||||
nationCnt: number,
|
||||
otherTextInfo: string,
|
||||
defaultStatTotal: number,
|
||||
}
|
||||
|
||||
type MyInfo = {
|
||||
name: string,
|
||||
picture: string,
|
||||
serverPath?: string,
|
||||
}
|
||||
|
||||
type ServerDetailResponse = {
|
||||
reserved?: ReservedGameInfo;
|
||||
game: GameInfo;
|
||||
me: MyInfo | null | undefined;
|
||||
}
|
||||
|
||||
$(function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
$("#btn_logout").on('click', Entrance_Logout);
|
||||
void Entrance_UpdateServer();
|
||||
if(isAdmin){
|
||||
void loadAdminPlugin();
|
||||
}
|
||||
});
|
||||
|
||||
async function Entrance_UpdateServer() {
|
||||
let data: RawServerResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_server_get_status.php',
|
||||
responseType: 'json',
|
||||
method: 'post'
|
||||
});
|
||||
data = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
alert(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
await Entrance_drawServerList(data.server);
|
||||
}
|
||||
|
||||
async function Entrance_drawServerList(serverInfos: ServerResponseItem[]) {
|
||||
const $serverList = $('#server_list');
|
||||
const now = getDateTimeNow();
|
||||
|
||||
const serverDetailInfoP: Record<string, Promise<ServerDetailResponse>> = {};
|
||||
|
||||
for (const serverInfo of serverInfos) {
|
||||
if(!serverInfo.exists){
|
||||
continue;
|
||||
}
|
||||
const responseP = axios({
|
||||
url: `../${serverInfo.name}/j_server_basic_info.php`,
|
||||
method: 'get',
|
||||
responseType: 'json'
|
||||
}).then(v=>{
|
||||
return v.data as ServerDetailResponse;
|
||||
});
|
||||
serverDetailInfoP[serverInfo.name] = responseP;
|
||||
}
|
||||
for (const serverInfo of serverInfos) {
|
||||
const $serverHtml = $(TemplateEngine(serverListTemplate, serverInfo));
|
||||
$serverList.append($serverHtml);
|
||||
if (!serverInfo.exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const serverPath = `../${serverInfo.name}`;
|
||||
|
||||
let response: ServerDetailResponse;
|
||||
try{
|
||||
if(!(serverInfo.name in serverDetailInfoP)){
|
||||
continue;
|
||||
}
|
||||
response = await serverDetailInfoP[serverInfo.name];
|
||||
}
|
||||
catch(e){
|
||||
console.error(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!response.game){
|
||||
continue;
|
||||
}
|
||||
|
||||
const game = response.game;
|
||||
|
||||
//TODO: 서버 폐쇄 방식을 새롭게 변경
|
||||
$serverHtml.find('.server_down').detach();
|
||||
|
||||
if (game.isUnited == 3) {
|
||||
$serverHtml.find('.n_country').html('§이벤트 종료§');
|
||||
$serverHtml.find('.server_date').html(`${game.starttime} <br>~ ${game.turntime}`);
|
||||
} else if (game.isUnited == 1) {
|
||||
$serverHtml.find('.n_country').html('§이벤트 진행중§');
|
||||
$serverHtml.find('.server_date').html(`${game.starttime} ~`);
|
||||
} else if (game.isUnited == 2) {
|
||||
$serverHtml.find('.n_country').html('§천하통일§');
|
||||
$serverHtml.find('.server_date').html(`${game.starttime} <br>~ ${game.turntime}`);
|
||||
} else if (game.opentime <= now) {
|
||||
$serverHtml.find('.n_country').html(`<${game.nationCnt}국 경쟁중>`);
|
||||
$serverHtml.find('.server_date').html(`${game.starttime} ~`);
|
||||
} else {
|
||||
$serverHtml.find('.n_country').html('-가오픈 중-');
|
||||
$serverHtml.find('.server_date').html(`${game.starttime} ~`);
|
||||
}
|
||||
|
||||
if (game.opentime <= now) {
|
||||
$serverHtml.append(
|
||||
TemplateEngine(serverTextInfo, game)
|
||||
);
|
||||
} else {
|
||||
$serverHtml.append(
|
||||
TemplateEngine(serverProvisionalInfo, game)
|
||||
);
|
||||
}
|
||||
|
||||
if (response.me && response.me.name) {
|
||||
const me = response.me;
|
||||
me.serverPath = serverPath;
|
||||
$serverHtml.append(
|
||||
TemplateEngine(serverLoginTemplate, me)
|
||||
);
|
||||
} else if (game.userCnt >= game.maxUserCnt) {
|
||||
$serverHtml.append(
|
||||
TemplateEngine(serverFullTemplate, {})
|
||||
);
|
||||
} else {
|
||||
$serverHtml.append(
|
||||
TemplateEngine(serverCreateTemplate, {
|
||||
serverPath: serverPath,
|
||||
canCreate: !game.block_general_create,
|
||||
canSelectNPC: game.npcMode == '가능',
|
||||
canSelectPool: game.npcMode == '선택 생성'
|
||||
})
|
||||
)
|
||||
}
|
||||
initTooltip($serverHtml);
|
||||
}
|
||||
}
|
||||
|
||||
async function Entrance_Logout() {
|
||||
const response = await axios({
|
||||
url: 'j_logout.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
});
|
||||
|
||||
const data: InvalidResponse = response.data;
|
||||
if(!data.result){
|
||||
alert(`로그아웃 실패: ${data.reason}`);
|
||||
return;
|
||||
}
|
||||
location.href = "../";
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
|
||||
import $ from 'jquery';
|
||||
import axios from 'axios';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { InvalidResponse } from '../defs';
|
||||
import { JQValidateForm, NamedRules } from '../util/jqValidateForm';
|
||||
import { convertFormData } from '../util/convertFormData';
|
||||
import { unwrap_any } from '../util/unwrap_any';
|
||||
import { mb_strwidth } from '../util/mb_strwidth';
|
||||
import { isString } from 'lodash';
|
||||
import { sha512 } from 'js-sha512';
|
||||
|
||||
async function changeInstallMode() {
|
||||
let result: {
|
||||
step: string,
|
||||
globalSalt: string,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_install_status.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
});
|
||||
result = response.data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`에러: ${e}`);
|
||||
return;
|
||||
}
|
||||
if (result.step == 'config') {
|
||||
$('#db_form_card').show();
|
||||
$('#admin_form_card').hide();
|
||||
return;
|
||||
}
|
||||
if (result.step == 'admin') {
|
||||
$('#db_form_card').hide();
|
||||
$('#admin_form_card').show();
|
||||
$('#global_salt').val(result.globalSalt);
|
||||
return;
|
||||
}
|
||||
if (result.step == 'done') {
|
||||
alert('설치가 완료되었습니다.');
|
||||
window.location.href = "..";
|
||||
return;
|
||||
}
|
||||
if (result.step == 'conn_fail') {
|
||||
$('#db_form_card').hide();
|
||||
$('#admin_form_card').hide();
|
||||
alert('설치 이후 DB 설정이 변경된 것 같습니다. RootDB.php 파일의 설정을 확인해주십시오.');
|
||||
return;
|
||||
}
|
||||
if (result.step == 'sql_fail') {
|
||||
$('#db_form_card').hide();
|
||||
$('#admin_form_card').hide();
|
||||
alert('DB가 제대로 설정되지 않았거나, 훼손된 것 같습니다. DB를 복구하거나 RootDB.php 파일을 삭제 후 재설치를 진행해 주십시오.');
|
||||
return;
|
||||
}
|
||||
|
||||
alert(`알 수 없는 오류: ${result}`);
|
||||
}
|
||||
|
||||
function setupDBForm() {
|
||||
const parentPathname = location.pathname.split('/').slice(0, -2).join('/');
|
||||
$('#serv_host').val(
|
||||
[location.protocol, '//', location.host, parentPathname].join('')
|
||||
);
|
||||
|
||||
$('#btn_random_generate_key').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
let token = '';
|
||||
while (token.length < 24) {
|
||||
token += (Math.random() + 1).toString(36).substring(7);
|
||||
}
|
||||
token = token.substr(0, 24);
|
||||
$('#image_request_key').val(token);
|
||||
});
|
||||
|
||||
type DBFormType = {
|
||||
db_host: string,
|
||||
db_port: string,
|
||||
db_id: string,
|
||||
db_pw: string,
|
||||
db_name: string,
|
||||
serv_host: string,
|
||||
shared_icon_path: string,
|
||||
game_image_path: string,
|
||||
image_request_key: string,
|
||||
kakao_rest_key: string,
|
||||
kakao_admin_key: string,
|
||||
}
|
||||
const descriptor: NamedRules<DBFormType> = {
|
||||
db_host: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
db_port: {
|
||||
required: true,
|
||||
type: 'number',
|
||||
transform: parseInt,
|
||||
},
|
||||
db_id: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
db_pw: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
db_name: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
serv_host: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
shared_icon_path: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
game_image_path: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
},
|
||||
image_request_key: {
|
||||
required: false,
|
||||
type: 'string',
|
||||
min: 16,
|
||||
},
|
||||
kakao_rest_key: {
|
||||
required: false,
|
||||
type: 'string',
|
||||
},
|
||||
kakao_admin_key: {
|
||||
required: false,
|
||||
type: 'string',
|
||||
}
|
||||
}
|
||||
const validator = new JQValidateForm($('#db_form'), descriptor);
|
||||
validator.installChangeHandler();
|
||||
|
||||
$('#db_form').on('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
const values = await validator.validate();
|
||||
if (values === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_setup_db.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
db_host: values.db_host,
|
||||
db_port: values.db_port,
|
||||
db_id: values.db_id,
|
||||
db_pw: values.db_pw,
|
||||
db_name: values.db_name,
|
||||
serv_host: values.serv_host,
|
||||
shared_icon_path: values.shared_icon_path,
|
||||
game_image_path: values.game_image_path,
|
||||
image_request_key: values.image_request_key,
|
||||
kakao_rest_key: values.kakao_rest_key,
|
||||
kakao_admin_key: values.kakao_admin_key,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`에러: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('RootDB.php가 생성되었습니다. 관리자 계정 생성을 진행합니다.');
|
||||
await changeInstallMode();
|
||||
});
|
||||
}
|
||||
|
||||
function maxStrWidth(maxWidth: number) {
|
||||
return (rule: unknown, value: string) => {
|
||||
if (!value || !isString(value) || mb_strwidth(value) > maxWidth) {
|
||||
return new Error(`글자 너비가 알파벳 ${maxWidth} 자보다 길지 않아야합니다`);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function setupAdminForm() {
|
||||
type AdminValues = {
|
||||
username: string,
|
||||
password: string,
|
||||
confirm_password: string,
|
||||
nickname: string,
|
||||
}
|
||||
const descriptor: NamedRules<AdminValues> = {
|
||||
username: {
|
||||
required: true,
|
||||
min: 4,
|
||||
max: 64,
|
||||
type: 'string',
|
||||
options: {//FIXME: options.messages가 동작하지 않는다?
|
||||
messages: {
|
||||
required: "유저명을 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `${l}글자 이상 입력하셔야 합니다`,
|
||||
max: (v, l) => `${l}자를 넘을 수 없습니다`,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
min: 6,
|
||||
options: {
|
||||
messages: {
|
||||
required: "비밀번호를 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `비밀번호는 적어도 ${l}글자 이상이어야 합니다`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirm_password: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
min: 6,
|
||||
validator: (rule, value: string, _callback, source) => {
|
||||
console.log(value);
|
||||
if (value != (source.password ?? '')) {
|
||||
return new Error('비밀번호가 일치하지 않습니다');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
options: {
|
||||
messages: {
|
||||
required: "비밀번호를 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `비밀번호는 적어도 ${l}글자 이상이어야 합니다`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nickname: {
|
||||
required: true,
|
||||
validator: maxStrWidth(18),
|
||||
options: {
|
||||
messages: {
|
||||
required: "유저명을 입력해주세요",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
const validator = new JQValidateForm($('#db_form'), descriptor);
|
||||
validator.installChangeHandler();
|
||||
|
||||
$('#admin_form').on('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
const values = await validator.validate();
|
||||
if (values === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const raw_password = values.password;
|
||||
const salt = unwrap_any<string>($('#global_salt').val());
|
||||
console.log(salt + raw_password + salt);
|
||||
const hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
let result: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_setup_db.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
nickname: values.nickname,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert(`에러: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('RootDB.php가 생성되었습니다. 관리자 계정 생성을 진행합니다.');
|
||||
await changeInstallMode();
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
void changeInstallMode();
|
||||
setupDBForm();
|
||||
setupAdminForm();
|
||||
|
||||
|
||||
|
||||
});
|
||||
@@ -0,0 +1,189 @@
|
||||
import $ from 'jquery';
|
||||
import axios from 'axios';
|
||||
import { JQValidateForm, NamedRules } from '../util/jqValidateForm';
|
||||
import { convertFormData } from '../util/convertFormData';
|
||||
import { InvalidResponse } from '../defs';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { unwrap_any } from '../util/unwrap_any';
|
||||
import { sha512 } from 'js-sha512';
|
||||
import { isString } from 'lodash';
|
||||
import { mb_strwidth } from '../util/mb_strwidth';
|
||||
|
||||
$(async function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
const terms1P = axios('../terms.1.html');
|
||||
const terms2P = axios('../terms.2.html');
|
||||
|
||||
type JoinFormType = {
|
||||
secret_agree: boolean,
|
||||
secret_agree2: boolean,
|
||||
third_use: boolean,
|
||||
username: string,
|
||||
password: string,
|
||||
confirm_password: string,
|
||||
nickname: string,
|
||||
}
|
||||
const descriptor: NamedRules<JoinFormType> = {
|
||||
username: {
|
||||
required: true,
|
||||
min: 4,
|
||||
max: 64,
|
||||
type: 'string',
|
||||
asyncValidator: async (rule, value: string) => {
|
||||
const response = await axios({
|
||||
url: 'j_check_dup.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
type: 'username',
|
||||
value: value,
|
||||
})
|
||||
});
|
||||
const isValid: boolean|string = response.data;
|
||||
if (isString(isValid)) {
|
||||
throw new Error(isValid);
|
||||
}
|
||||
},
|
||||
options: {//FIXME: options.messages가 동작하지 않는다?
|
||||
messages: {
|
||||
required: "유저명을 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `${l}글자 이상 입력하셔야 합니다`,
|
||||
max: (v, l) => `${l}자를 넘을 수 없습니다`,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
min: 6,
|
||||
options: {
|
||||
messages: {
|
||||
required: "비밀번호를 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `비밀번호는 적어도 ${l}글자 이상이어야 합니다`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirm_password: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
min: 6,
|
||||
validator: (rule, value: string, _callback, source) => {
|
||||
console.log(value);
|
||||
if (value != (source.password ?? '')) {
|
||||
return new Error('비밀번호가 일치하지 않습니다');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
options: {
|
||||
messages: {
|
||||
required: "비밀번호를 입력해주세요",
|
||||
string: {
|
||||
min: (v, l) => `비밀번호는 적어도 ${l}글자 이상이어야 합니다`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nickname: {
|
||||
required: true,
|
||||
asyncValidator: async (rule, value: string) => {
|
||||
if (!value || !isString(value) || mb_strwidth(value) > 18) {
|
||||
throw new Error(`글자 너비가 알파벳 ${18}자보다 길지 않아야합니다`);
|
||||
}
|
||||
const response = await axios({
|
||||
url: 'j_check_dup.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
type: 'nickname',
|
||||
value: value,
|
||||
})
|
||||
});
|
||||
const isValid: boolean|string = response.data;
|
||||
if (isString(isValid)) {
|
||||
throw new Error(isValid);
|
||||
}
|
||||
},
|
||||
options: {
|
||||
messages: {
|
||||
required: "유저명을 입력해주세요",
|
||||
}
|
||||
}
|
||||
},
|
||||
secret_agree: {
|
||||
required: true,
|
||||
transform: (v)=>v=='on',
|
||||
type: 'enum',
|
||||
enum: [true],
|
||||
message: '동의해야만 가입하실 수 있습니다.',
|
||||
},
|
||||
secret_agree2: {
|
||||
required: true,
|
||||
transform: (v)=>v=='on',
|
||||
type: 'enum',
|
||||
enum: [true],
|
||||
message: '동의해야만 가입하실 수 있습니다.',
|
||||
},
|
||||
third_use: {
|
||||
required: true,
|
||||
transform: (v)=>v=='on',
|
||||
type: 'boolean'
|
||||
}
|
||||
}
|
||||
const validator = new JQValidateForm($('#main_form'), descriptor);
|
||||
validator.installChangeHandler();
|
||||
|
||||
$("#main_form").on('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const values = await validator.validate();
|
||||
if (values === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const raw_password = values.password;
|
||||
const salt = unwrap_any<string>($('#global_salt').val());
|
||||
console.log(salt + raw_password + salt);
|
||||
const hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_join_process.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
secret_agree: values.secret_agree,
|
||||
secret_agree2: values.secret_agree2,
|
||||
third_use: values.third_use,
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
nickname: values.nickname,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
window.location.href = "../";
|
||||
return;
|
||||
}
|
||||
|
||||
alert('회원 등록되었습니다.\n첫 로그인 과정에서 인증 코드를 입력하는 것으로 계정이 활성화됩니다.');
|
||||
window.location.href = "../";
|
||||
});
|
||||
|
||||
$('#terms1').html((await terms1P).data);
|
||||
$('#terms2').html((await terms2P).data);
|
||||
});
|
||||
@@ -0,0 +1,299 @@
|
||||
import $ from 'jquery';
|
||||
import 'popper.js';
|
||||
import Popper from 'popper.js';
|
||||
(window as unknown as {Popper:unknown}).Popper = Popper;
|
||||
import 'bootstrap';
|
||||
import { JQValidateForm, NamedRules } from '../util/jqValidateForm';
|
||||
import axios from 'axios';
|
||||
import { convertFormData } from '../util/convertFormData';
|
||||
import { setAxiosXMLHttpRequest } from '../util/setAxiosXMLHttpRequest';
|
||||
import { unwrap_any } from '../util/unwrap_any';
|
||||
import { sha512 } from 'js-sha512';
|
||||
import { unwrap } from '../util/unwrap';
|
||||
import { InvalidResponse } from '../defs';
|
||||
|
||||
|
||||
type LoginResponse = {
|
||||
result: true,
|
||||
} | {
|
||||
result: false,
|
||||
reqOTP: boolean,
|
||||
reason: string,
|
||||
}
|
||||
|
||||
type OTPResponse = {
|
||||
result: true,
|
||||
validUntil: string,
|
||||
} | {
|
||||
result: false,
|
||||
reset: boolean,
|
||||
reason: string,
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
getOAuthToken: (mode: string, scope_list: string[]) => void;
|
||||
postOAuthResult: (mode: string) => void;
|
||||
}
|
||||
}
|
||||
|
||||
declare const kakao_oauth_client_id: string;
|
||||
declare const kakao_oauth_redirect_uri: string;
|
||||
|
||||
let oauthMode: string | null = null;
|
||||
|
||||
function getOAuthToken(mode: string, scope_list?: string[] | string) {
|
||||
if (mode === undefined) {
|
||||
mode = 'login';
|
||||
}
|
||||
oauthMode = mode;
|
||||
let url = `https://kauth.kakao.com/oauth/authorize?client_id=${kakao_oauth_client_id}&redirect_uri=${kakao_oauth_redirect_uri}&response_type=code`;
|
||||
if (Array.isArray(scope_list)) {
|
||||
url += `&scope=${scope_list.join(',')}`;
|
||||
} else if (typeof scope_list === 'string') {
|
||||
url += `&scope=${scope_list}`;
|
||||
}
|
||||
|
||||
window.open(url, "KakaoAccountLogin", "width=600,height=450,resizable=yes,scrollbars=yes");
|
||||
}
|
||||
window.getOAuthToken = getOAuthToken;
|
||||
|
||||
async function sendTempPasswordToKakaoTalk(): Promise<void> {
|
||||
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다_login: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'oauth_kakao/j_change_pw.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다_pw: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('임시 비밀번호가 카카오톡으로 전송되었습니다.');
|
||||
}
|
||||
|
||||
async function doLoginUsingOAuth() {
|
||||
let result: LoginResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다_login: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.reqOTP) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
const $modal = $('#modalOTP').modal();
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
$('#otp_code').trigger('focus');
|
||||
});
|
||||
}
|
||||
|
||||
function postOAuthResult(mode: string) {
|
||||
if (mode == 'join') {
|
||||
window.location.href = 'oauth_kakao/join.php';
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 'req_email') {
|
||||
alert('이메일 정보 공유를 허가해 주셔야 합니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 'login') {
|
||||
console.log('로그인모드');
|
||||
if (oauthMode == 'change_pw') {
|
||||
void sendTempPasswordToKakaoTalk();
|
||||
} else {
|
||||
void doLoginUsingOAuth();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
alert('예외 발생!');
|
||||
}
|
||||
window.postOAuthResult = postOAuthResult;
|
||||
|
||||
|
||||
$(function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
type LoginFormType = {
|
||||
username: string,
|
||||
password: string,
|
||||
};
|
||||
const descriptor: NamedRules<LoginFormType> = {
|
||||
username: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '유저명을 입력해주세요',
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '비밀번호를 입력해주세요'
|
||||
}
|
||||
};
|
||||
|
||||
const validator = new JQValidateForm($('#main_form'), descriptor);
|
||||
validator.installChangeHandler();
|
||||
|
||||
$("#main_form").on('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const values = await validator.validate();
|
||||
if (values === undefined) {
|
||||
return;
|
||||
}
|
||||
const raw_password = values.password;
|
||||
const salt = unwrap_any<string>($('#global_salt').val());
|
||||
const hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
let result: LoginResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_login.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (result.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.reqOTP) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
const $modal = $('#modalOTP').modal();
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
$('#otp_code').trigger('focus');
|
||||
});
|
||||
});
|
||||
|
||||
$('#otp_form').on('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
let result: OTPResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'oauth_kakao/j_check_OTP.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
otp: unwrap_any<string>($('#otp_code').val()),
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.result) {
|
||||
alert(`로그인되었습니다. ${result.validUntil}까지 유효합니다.`);
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
alert(result.reason);
|
||||
|
||||
if (result.reset) {
|
||||
$('#modalOTP').modal('hide')
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
$('#oauth_change_pw').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
getOAuthToken('change_pw', 'talk_message');
|
||||
});
|
||||
|
||||
$('#btn_kakao_login').on('click', function(e){
|
||||
e.preventDefault();
|
||||
getOAuthToken('login', ['account_email','talk_message']);
|
||||
})
|
||||
|
||||
|
||||
//TODO: 모바일에서 크기 비례 지도 다시 띄우기?
|
||||
/*
|
||||
if (document.body.clientWidth < 700) {
|
||||
const targetWidth = document.body.clientWidth * 0.9;
|
||||
const scale = targetWidth / 700;
|
||||
const $map = $('#running_map');
|
||||
$map.find('.col').css('max-width', targetWidth);
|
||||
$map.find('.card').css('width', targetWidth);
|
||||
$map.find('.map-container').css({
|
||||
'transform-origin': 'top left',
|
||||
'transform': `scale(${scale}, ${scale})`,
|
||||
'height': 500 * scale,
|
||||
});
|
||||
$map.find('.map_body').data('scale', scale);
|
||||
}*/
|
||||
});
|
||||
|
||||
window.fitIframe = function () {
|
||||
const iframe = unwrap(document.querySelector<HTMLIFrameElement>('#running_map'));//TODO: 근황 여러개 볼 수 있도록?
|
||||
const scrollHeight = unwrap(iframe.contentWindow).document.body.scrollHeight;
|
||||
iframe.style.height = `${scrollHeight}px`;
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
import { setAxiosXMLHttpRequest } from "../util/setAxiosXMLHttpRequest";
|
||||
import $ from 'jquery';
|
||||
import Popper from 'popper.js';
|
||||
exportWindow(Popper, 'Popper');//XXX: 왜 popper를 이렇게 불러야 하는가?
|
||||
import 'bootstrap';
|
||||
import axios from 'axios';
|
||||
import { subDays } from 'date-fns';
|
||||
import { getDateTimeNow } from "../util/getDateTimeNow";
|
||||
import { sha512 } from "js-sha512";
|
||||
import { convertFormData } from "../util/convertFormData";
|
||||
import { InvalidResponse } from "../defs";
|
||||
import { unwrap } from "../util/unwrap";
|
||||
import { parseTime } from "../util/parseTime";
|
||||
import { formatTime } from "../util/formatTime";
|
||||
import { exportWindow } from "../util/exportWindow";
|
||||
|
||||
type ResultUserInfo = {
|
||||
result: true,
|
||||
id: number,
|
||||
name: string,
|
||||
grade: string,
|
||||
picture: string,
|
||||
global_salt: string,
|
||||
join_date: string,
|
||||
third_use: boolean,
|
||||
acl: string,
|
||||
oauth_type: 'NONE' | 'KAKAO',
|
||||
token_valid_until?: string
|
||||
}
|
||||
|
||||
function fillUserInfo(result: ResultUserInfo | InvalidResponse) {
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
location.href = 'entrance.php';
|
||||
return;
|
||||
}
|
||||
|
||||
$('#slot_id').html(result.id.toString());
|
||||
$('#slot_nickname').html(result.name);
|
||||
$('#slot_grade').html(result.grade);
|
||||
$('#slot_acl').html(result.acl);
|
||||
$('#slot_icon').attr('src', result.picture);
|
||||
$('#global_salt').val(result.global_salt);
|
||||
$('#slot_join_date').html(result.join_date);
|
||||
$('#slot_third_use').html(result.third_use ? '○' : '×');
|
||||
if (result.third_use) {
|
||||
$('#third_use_disallow').show();
|
||||
}
|
||||
$('#slot_oauth_type').text(result.oauth_type);
|
||||
if (result.oauth_type != 'NONE') {
|
||||
$('#slot_token_valid_until').text(unwrap(result.token_valid_until));
|
||||
}
|
||||
else {
|
||||
$('#slot_token_valid_until').parent().html('');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function changeIconPreview(this: HTMLFormElement) {
|
||||
const $preview = $(this) as JQuery<HTMLFormElement>;
|
||||
console.log($preview);
|
||||
|
||||
const filename = $preview[0].files[0].name;
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
$('#slot_new_icon').attr('src', unwrap(unwrap(e.target).result).toString()).css('visibility', 'visible');
|
||||
}
|
||||
|
||||
reader.readAsDataURL($preview[0].files[0]);
|
||||
|
||||
$('#image_upload_filename').val(filename);
|
||||
}
|
||||
|
||||
type IconResponse = {
|
||||
result: true,
|
||||
servers: [string, string][]
|
||||
};
|
||||
|
||||
async function deleteIcon() {
|
||||
let result: InvalidResponse | IconResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_icon_delete.php',
|
||||
responseType: 'json',
|
||||
method: 'post'
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`아이콘 삭제를 실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
showAdjustServerModal(result.servers);
|
||||
}
|
||||
|
||||
async function disallowThirdUse() {
|
||||
try {
|
||||
await axios({
|
||||
url: 'j_disallow_third_use.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
});
|
||||
alert('철회했습니다.');
|
||||
}
|
||||
catch (e) {
|
||||
alert('알 수 없는 이유로 철회를 실패했습니다.');
|
||||
}
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function showAdjustServerModal(serverList: [string, string][]) {
|
||||
|
||||
const $form = $('#chooseServerForm');
|
||||
$form.empty();
|
||||
|
||||
for (const [serverKey, serverKorName] of serverList) {
|
||||
const $item = $(`<div style="display:inline-block;margin-right:7px;" class="custom-control custom-checkbox">\
|
||||
<input type="checkbox" checked class="custom-control-input" name="${serverKey}" id="switch_${serverKey}">\
|
||||
<label class="custom-control-label" for="switch_${serverKey}">${serverKorName}</label>\
|
||||
</div>`);
|
||||
$form.append($item);
|
||||
}
|
||||
|
||||
const $modal = $('#chooseServer');
|
||||
$modal.modal({
|
||||
backdrop: 'static'
|
||||
});
|
||||
$modal.on('hidden.bs.modal', function () {
|
||||
location.reload();
|
||||
return;
|
||||
});
|
||||
|
||||
$("#modal-apply").off("click").on("click", async function () {
|
||||
const events: Promise<unknown>[] = [];
|
||||
$form.find('input:checked').each(function () {
|
||||
const $input = $(this);
|
||||
const server = $input.attr('name');
|
||||
|
||||
console.log(server);
|
||||
|
||||
events.push(axios({
|
||||
url: `../${server}/j_adjust_icon.php`,
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
}));
|
||||
})
|
||||
|
||||
for (const p of events) {
|
||||
try {
|
||||
await p;
|
||||
}
|
||||
catch (e) {
|
||||
//서버 폐쇄등으로 접근하지 못할 수도 있음.
|
||||
console.error(e, p);
|
||||
}
|
||||
}
|
||||
|
||||
alert('적용되었습니다.');
|
||||
location.reload();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async function changeIcon(this: HTMLFormElement) {
|
||||
const $icon = $('#image_upload') as JQuery<HTMLFormElement>;
|
||||
|
||||
if ($icon[0].files.length == 0) {
|
||||
alert('파일을 선택해주세요');
|
||||
return false;
|
||||
}
|
||||
|
||||
let result: InvalidResponse | IconResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_icon_change.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: new FormData(this)
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
alert('알 수 없는 이유로 아이콘 업로드를 실패했습니다.');
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
showAdjustServerModal(result.servers);
|
||||
}
|
||||
|
||||
async function changePassword() {
|
||||
const old_pw = $('#current_pw').val() as string;
|
||||
const new_pw = $('#new_pw').val() as string;
|
||||
const new_pw_confirm = $('#new_pw_confirm').val() as string;
|
||||
|
||||
if (!old_pw) {
|
||||
alert('이전 비밀번호를 입력해야 합니다.');
|
||||
return;
|
||||
}
|
||||
if (new_pw.length < 6) {
|
||||
alert('비밀번호 길이는 6글자 이상이어야 합니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_pw != new_pw_confirm) {
|
||||
alert('입력 값이 일치하지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const global_salt = $('#global_salt').val();
|
||||
|
||||
const old_password = sha512(global_salt + old_pw + global_salt);
|
||||
const new_password = sha512(global_salt + new_pw + global_salt);
|
||||
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_change_password.php',
|
||||
method: 'post',
|
||||
responseType: 'json',
|
||||
data: convertFormData({
|
||||
old_pw: old_password,
|
||||
new_pw: new_password
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`알 수 없는 이유로 비밀번호를 바꾸지 못했습니다.: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('비밀번호를 바꾸었습니다');
|
||||
location.reload();
|
||||
}
|
||||
|
||||
async function deleteMe() {
|
||||
const pw = $('#delete_pw').val() as string;
|
||||
|
||||
if (!pw) {
|
||||
alert('비밀번호를 입력해야 합니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const global_salt = $('#global_salt').val();
|
||||
|
||||
const password = sha512(global_salt + pw + global_salt);
|
||||
|
||||
let data: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_delete_me.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
pw: password
|
||||
})
|
||||
});
|
||||
data = response.data;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`회원 탈퇴에 실패했습니다.: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.result) {
|
||||
alert(data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('탈퇴 처리되었습니다.');
|
||||
location.href = '../';
|
||||
}
|
||||
|
||||
async function extendAuth() {
|
||||
const validUntil = $('#slot_token_valid_until').html();
|
||||
const availableAt = formatTime(subDays(parseTime(validUntil), 5));
|
||||
const now = getDateTimeNow();
|
||||
|
||||
if (now < availableAt) {
|
||||
alert(`${availableAt}부터 초기화할 수 있습니다.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!confirm('로그아웃됩니다. 진행할까요?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: '../oauth_kakao/j_reset_token.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
})
|
||||
result = response.data;
|
||||
} catch (e) {
|
||||
alert(`알 수 없는 이유로 로그인 토큰 연장에 실패했습니다. : ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.result) {
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('초기화했습니다. 다시 로그인해 주십시오.');
|
||||
location.href = '../';
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
$('#slot_icon, #slot_new_icon').attr('src', window.pathConfig.sharedIcon + '/default.jpg');
|
||||
|
||||
axios({
|
||||
url: 'j_get_user_info.php',
|
||||
method: 'post',
|
||||
responseType: 'json'
|
||||
}).then(result => {
|
||||
fillUserInfo(result.data);
|
||||
}, () => {
|
||||
alert('알 수 없는 이유로, 회원 정보를 불러오지 못했습니다.');
|
||||
location.href = 'entrance.php';
|
||||
})
|
||||
|
||||
$('#image_upload').on('change', changeIconPreview);
|
||||
|
||||
$('#btn_remove_icon').on('click', function () {
|
||||
if (confirm('아이콘을 제거할까요?')) {
|
||||
void deleteIcon();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#third_use_disallow').on('click', function () {
|
||||
if (confirm('개인정보 3자 제공 동의를 철회할까요?')) {
|
||||
void disallowThirdUse();
|
||||
}
|
||||
});
|
||||
|
||||
$('#change_pw_form').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
void changePassword();
|
||||
});
|
||||
|
||||
$('#change_icon_form').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
void changeIcon.apply(this as HTMLFormElement);
|
||||
});
|
||||
|
||||
$('#delete_me_form').on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
if (confirm('한 달 동안 재 가입할 수 없습니다. 정말로 탈퇴할까요?')) {
|
||||
void deleteMe();
|
||||
}
|
||||
});
|
||||
|
||||
$('#expand_login_token').on('click', extendAuth);
|
||||
})
|
||||
Reference in New Issue
Block a user