add password reset
This commit is contained in:
parent
41c0c39620
commit
14401b2784
26
app.ts
26
app.ts
@ -1,8 +1,20 @@
|
|||||||
import { app, BrowserWindow, session, dialog } from "electron";
|
import { app, BrowserWindow, session, dialog } from "electron";
|
||||||
import { get_setting } from "./src/SettingConfig";
|
import { get_setting } from "./src/SettingConfig";
|
||||||
import { create_server, start_server } from "./src/server";
|
import { create_server } from "./src/server";
|
||||||
import { getAdminAccessTokenValue,getAdminRefreshTokenValue, accessTokenName, refreshTokenName } from "./src/login";
|
import { getAdminAccessTokenValue,getAdminRefreshTokenValue, accessTokenName, refreshTokenName } from "./src/login";
|
||||||
|
import { join } from "path";
|
||||||
|
import { ipcMain } from 'electron';
|
||||||
|
import { UserAccessor } from "./src/model/mod";
|
||||||
|
function registerChannel(cntr: UserAccessor){
|
||||||
|
ipcMain.handle('reset_password', async(event,username:string,password:string)=>{
|
||||||
|
const user = await cntr.findUser(username);
|
||||||
|
if(user === undefined){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
user.reset_password(password);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
const setting = get_setting();
|
const setting = get_setting();
|
||||||
if (!setting.cli) {
|
if (!setting.cli) {
|
||||||
let wnd: BrowserWindow | null = null;
|
let wnd: BrowserWindow | null = null;
|
||||||
@ -13,9 +25,14 @@ if (!setting.cli) {
|
|||||||
height: 600,
|
height: 600,
|
||||||
center: true,
|
center: true,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
|
webPreferences:{
|
||||||
|
preload:join(__dirname,'preload.js'),
|
||||||
|
contextIsolation:true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
await wnd.loadURL(`data:text/html;base64,`+Buffer.from(loading_html).toString('base64'));
|
await wnd.loadURL(`data:text/html;base64,`+Buffer.from(loading_html).toString('base64'));
|
||||||
//await wnd.loadURL('../loading.html');
|
//await wnd.loadURL('../loading.html');
|
||||||
|
//set admin cookies.
|
||||||
await session.defaultSession.cookies.set({
|
await session.defaultSession.cookies.set({
|
||||||
url:`http://localhost:${setting.port}`,
|
url:`http://localhost:${setting.port}`,
|
||||||
name:accessTokenName,
|
name:accessTokenName,
|
||||||
@ -34,7 +51,8 @@ if (!setting.cli) {
|
|||||||
});
|
});
|
||||||
try{
|
try{
|
||||||
const server = await create_server();
|
const server = await create_server();
|
||||||
start_server(server);
|
server.start_server();
|
||||||
|
registerChannel(server.userController);
|
||||||
await wnd.loadURL(`http://localhost:${setting.port}`);
|
await wnd.loadURL(`http://localhost:${setting.port}`);
|
||||||
}
|
}
|
||||||
catch(e){
|
catch(e){
|
||||||
@ -85,7 +103,7 @@ if (!setting.cli) {
|
|||||||
} else {
|
} else {
|
||||||
(async () => {
|
(async () => {
|
||||||
const server = await create_server();
|
const server = await create_server();
|
||||||
start_server(server);
|
server.start_server();
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
const loading_html = `<!DOCTYPE html>
|
const loading_html = `<!DOCTYPE html>
|
||||||
|
@ -1 +1,7 @@
|
|||||||
import {} from 'electron';
|
import {ipcRenderer, contextBridge} from 'electron';
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('electron',{
|
||||||
|
passwordReset:async (username:string,toPw:string)=>{
|
||||||
|
return await ipcRenderer.invoke('reset_password',username,toPw);
|
||||||
|
}
|
||||||
|
});
|
@ -1,11 +1,24 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { CommonMenuList, Headline } from "../component/mod";
|
import { CommonMenuList, Headline } from "../component/mod";
|
||||||
import { UserContext } from "../state";
|
import { UserContext } from "../state";
|
||||||
import { Grid, Paper, Typography } from "@material-ui/core";
|
import { Box, Grid, Paper, Typography,Button, makeStyles, Theme } from "@material-ui/core";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme:Theme)=>({
|
||||||
|
paper:{
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
},
|
||||||
|
commitable:{
|
||||||
|
display:'grid',
|
||||||
|
gridTemplateColumns: `100px auto`,
|
||||||
|
},
|
||||||
|
contentTitle:{
|
||||||
|
marginLeft: theme.spacing(2)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
export function DifferencePage(){
|
export function DifferencePage(){
|
||||||
const ctx = useContext(UserContext);
|
const ctx = useContext(UserContext);
|
||||||
|
const classes = useStyles();
|
||||||
const [diffList,setDiffList] = useState<
|
const [diffList,setDiffList] = useState<
|
||||||
{type:string,value:{path:string,type:string}[]}[]
|
{type:string,value:{path:string,type:string}[]}[]
|
||||||
>([]);
|
>([]);
|
||||||
@ -44,9 +57,15 @@ export function DifferencePage(){
|
|||||||
const menu = CommonMenuList();
|
const menu = CommonMenuList();
|
||||||
(ctx.username == "admin")
|
(ctx.username == "admin")
|
||||||
return (<Headline menu={menu}>
|
return (<Headline menu={menu}>
|
||||||
{(ctx.username == "admin") ? (diffList.map(x=><Paper key={x.type}>
|
{(ctx.username == "admin") ? (diffList.map(x=><Paper key={x.type} className={classes.paper}>
|
||||||
<Typography variant='h3'>{x.type}</Typography>
|
<Typography variant='h3' className={classes.contentTitle}>{x.type}</Typography>
|
||||||
{x.value.map(y=>(<Typography key={y.path} variant='h5' onClick={()=>Commit(y)}>{y.path}</Typography>))}
|
<Box className={classes.commitable}>
|
||||||
|
{x.value.map(y=>(
|
||||||
|
<>
|
||||||
|
<Button key={`button_${y.path}`} onClick={()=>Commit(y)}>Commit</Button>
|
||||||
|
<Typography key={`typography_${y.path}`} variant='h5'>{y.path}</Typography>
|
||||||
|
</>))}
|
||||||
|
</Box>
|
||||||
</Paper>)):(<Typography variant='h2'>Not Allowed : please login as an admin</Typography>)
|
</Paper>)):(<Typography variant='h2'>Not Allowed : please login as an admin</Typography>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export const LoginPage = ()=>{
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [userLoginInfo,setUserLoginInfo]= useState({username:"",password:""});
|
const [userLoginInfo,setUserLoginInfo]= useState({username:"",password:""});
|
||||||
const [openDialog,setOpenDialog] = useState({open:false,message:""});
|
const [openDialog,setOpenDialog] = useState({open:false,message:""});
|
||||||
const {username,setUsername,permission,setPermission} = useContext(UserContext);
|
const {setUsername,setPermission} = useContext(UserContext);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const handleDialogClose = ()=>{
|
const handleDialogClose = ()=>{
|
||||||
setOpenDialog({...openDialog,open:false});
|
setOpenDialog({...openDialog,open:false});
|
||||||
|
@ -1,18 +1,98 @@
|
|||||||
import { CommonMenuList, Headline } from "../component/mod";
|
import { CommonMenuList, Headline } from "../component/mod";
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import { UserContext } from "../state";
|
import { UserContext } from "../state";
|
||||||
import { Grid, Paper, Typography } from "@material-ui/core";
|
import { Chip, Grid, makeStyles, Paper, Theme, Typography, Divider, Button,
|
||||||
|
Dialog, DialogTitle, DialogContentText, DialogContent, TextField, DialogActions } from "@material-ui/core";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme:Theme)=>({
|
||||||
|
paper:{
|
||||||
|
alignSelf:"center",
|
||||||
|
padding:theme.spacing(2),
|
||||||
|
},
|
||||||
|
formfield:{
|
||||||
|
display:'flex',
|
||||||
|
flexFlow:'column',
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
export function ProfilePage(){
|
export function ProfilePage(){
|
||||||
const userctx = useContext(UserContext);
|
const userctx = useContext(UserContext);
|
||||||
|
const classes = useStyles();
|
||||||
const menu = CommonMenuList();
|
const menu = CommonMenuList();
|
||||||
|
const [pw_open,set_pw_open] = useState(false);
|
||||||
|
const [oldpw,setOldpw] = useState("");
|
||||||
|
const [newpw,setNewpw] = useState("");
|
||||||
|
const [newpwch,setNewpwch] = useState("");
|
||||||
|
const [msg_dialog,set_msg_dialog] = useState({opened:false,msg:""});
|
||||||
|
const permission_list =userctx.permission.map(p=>(
|
||||||
|
<Chip key={p} label={p}></Chip>
|
||||||
|
));
|
||||||
|
const isElectronContent = window['electron'] !== undefined;
|
||||||
|
const handle_open = ()=>set_pw_open(true);
|
||||||
|
const handle_close = ()=>{
|
||||||
|
set_pw_open(false);
|
||||||
|
setNewpw("");
|
||||||
|
setNewpwch("");
|
||||||
|
};
|
||||||
|
const handle_ok= ()=>{
|
||||||
|
if(isElectronContent){
|
||||||
|
const elec = window['electron'];
|
||||||
|
if(newpw == newpwch){
|
||||||
|
const success = elec.passwordReset(userctx.username,newpw);
|
||||||
|
if(!success){
|
||||||
|
set_msg_dialog({opened:true,msg:"user not exist."});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
set_msg_dialog({opened:true,msg:"password and password check is not equal."});
|
||||||
|
}
|
||||||
|
handle_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
return (<Headline menu={menu}>
|
return (<Headline menu={menu}>
|
||||||
<Paper style={{alignSelf : 'center'}}>
|
<Paper className={classes.paper}>
|
||||||
<Grid container>
|
<Grid container direction="column" alignItems="center">
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Typography>{userctx.username}</Typography>
|
<Typography variant='h4'>{userctx.username}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Divider></Divider>
|
||||||
|
<Grid item>
|
||||||
|
Permission
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
{permission_list.length == 0 ? "-" : permission_list}
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Button onClick={handle_open}>Password Reset</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
<Dialog open={pw_open} onClose={handle_close}>
|
||||||
|
<DialogTitle>Password Reset</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>type the old and new password</Typography>
|
||||||
|
<div className={classes.formfield}>
|
||||||
|
{(!isElectronContent) && (<TextField autoFocus margin='dense' type="password" label="old password"
|
||||||
|
value={oldpw} onChange={(e)=>setOldpw(e.target.value)}></TextField>)}
|
||||||
|
<TextField margin='dense' type="password" label="new password"
|
||||||
|
value={newpw} onChange={e=>setNewpw(e.target.value)}></TextField>
|
||||||
|
<TextField margin='dense' type="password" label="new password check"
|
||||||
|
value={newpwch} onChange={e=>setNewpwch(e.target.value)}></TextField>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handle_close} color="primary">Cancel</Button>
|
||||||
|
<Button onClick={handle_ok} color="primary">Ok</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
<Dialog open={msg_dialog.opened} onClose={()=>set_msg_dialog({opened:false,msg:""})}>
|
||||||
|
<DialogTitle>Alert!</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>{msg_dialog.msg}</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={()=>set_msg_dialog({opened:false,msg:""})} color="primary">Close</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</Headline>)
|
</Headline>)
|
||||||
}
|
}
|
94
src/login.ts
94
src/login.ts
@ -35,12 +35,12 @@ const accessExpiredTime = 60 * 60; //1 hour
|
|||||||
const refreshExpiredTime = 60 * 60 * 24 * 14; // 14 day;
|
const refreshExpiredTime = 60 * 60 * 24 * 14; // 14 day;
|
||||||
|
|
||||||
export const getAdminAccessTokenValue = () => {
|
export const getAdminAccessTokenValue = () => {
|
||||||
const {jwt_secretkey} = get_setting();
|
const { jwt_secretkey } = get_setting();
|
||||||
return publishAccessToken(jwt_secretkey,"admin",[],accessExpiredTime);
|
return publishAccessToken(jwt_secretkey, "admin", [], accessExpiredTime);
|
||||||
};
|
};
|
||||||
export const getAdminRefreshTokenValue = () => {
|
export const getAdminRefreshTokenValue = () => {
|
||||||
const {jwt_secretkey} = get_setting();
|
const { jwt_secretkey } = get_setting();
|
||||||
return publishRefreshToken(jwt_secretkey,"admin",refreshExpiredTime);
|
return publishRefreshToken(jwt_secretkey, "admin", refreshExpiredTime);
|
||||||
};
|
};
|
||||||
const publishAccessToken = (
|
const publishAccessToken = (
|
||||||
secretKey: string,
|
secretKey: string,
|
||||||
@ -73,12 +73,12 @@ const publishRefreshToken = (
|
|||||||
const setToken = (
|
const setToken = (
|
||||||
ctx: Koa.Context,
|
ctx: Koa.Context,
|
||||||
token_name: string,
|
token_name: string,
|
||||||
token_payload: string|null,
|
token_payload: string | null,
|
||||||
expiredtime: number,
|
expiredtime: number,
|
||||||
) => {
|
) => {
|
||||||
const setting = get_setting();
|
const setting = get_setting();
|
||||||
if(token_payload === null && !!!ctx.cookies.get(token_name)){
|
if (token_payload === null && !!!ctx.cookies.get(token_name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.cookies.set(token_name, token_payload, {
|
ctx.cookies.set(token_name, token_payload, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
@ -87,9 +87,8 @@ const setToken = (
|
|||||||
expires: new Date(Date.now() + expiredtime),
|
expires: new Date(Date.now() + expiredtime),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const createLoginMiddleware = (knex: Knex) => {
|
export const createLoginMiddleware = (userController: UserAccessor) =>
|
||||||
const userController = createKnexUserController(knex);
|
async (ctx: Koa.Context, next: Koa.Next) => {
|
||||||
return async (ctx: Koa.Context, next: Koa.Next) => {
|
|
||||||
const setting = get_setting();
|
const setting = get_setting();
|
||||||
const secretKey = setting.jwt_secretkey;
|
const secretKey = setting.jwt_secretkey;
|
||||||
const body = ctx.request.body;
|
const body = ctx.request.body;
|
||||||
@ -143,16 +142,15 @@ export const createLoginMiddleware = (knex: Knex) => {
|
|||||||
console.log(`${username} logined`);
|
console.log(`${username} logined`);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
export const LogoutMiddleware = (ctx: Koa.Context, next: Koa.Next) => {
|
export const LogoutMiddleware = (ctx: Koa.Context, next: Koa.Next) => {
|
||||||
ctx.cookies.set(accessTokenName, null);
|
ctx.cookies.set(accessTokenName, null);
|
||||||
ctx.cookies.set(refreshTokenName,null);
|
ctx.cookies.set(refreshTokenName, null);
|
||||||
ctx.body = { ok: true };
|
ctx.body = { ok: true };
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
export const createUserMiddleWare = (knex: Knex) =>
|
export const createUserMiddleWare = (userController: UserAccessor) =>
|
||||||
async (ctx: Koa.ParameterizedContext<UserState>, next: Koa.Next) => {
|
async (ctx: Koa.ParameterizedContext<UserState>, next: Koa.Next) => {
|
||||||
const userController = createKnexUserController(knex);
|
|
||||||
const refreshToken = refreshTokenHandler(userController);
|
const refreshToken = refreshTokenHandler(userController);
|
||||||
const setting = get_setting();
|
const setting = get_setting();
|
||||||
const setGuest = async () => {
|
const setGuest = async () => {
|
||||||
@ -161,9 +159,10 @@ async (ctx: Koa.ParameterizedContext<UserState>, next: Koa.Next) => {
|
|||||||
ctx.state["user"] = { username: "", permission: setting.guest };
|
ctx.state["user"] = { username: "", permission: setting.guest };
|
||||||
return await next();
|
return await next();
|
||||||
};
|
};
|
||||||
return await refreshToken(ctx,setGuest,next);
|
return await refreshToken(ctx, setGuest, next);
|
||||||
};
|
};
|
||||||
const refreshTokenHandler = (cntr:UserAccessor) => async (ctx:Koa.Context,fail: Koa.Next,next: Koa.Next)=>{
|
const refreshTokenHandler = (cntr: UserAccessor) =>
|
||||||
|
async (ctx: Koa.Context, fail: Koa.Next, next: Koa.Next) => {
|
||||||
const payload = ctx.cookies.get(accessTokenName);
|
const payload = ctx.cookies.get(accessTokenName);
|
||||||
const setting = get_setting();
|
const setting = get_setting();
|
||||||
const secretKey = setting.jwt_secretkey;
|
const secretKey = setting.jwt_secretkey;
|
||||||
@ -215,31 +214,50 @@ const refreshTokenHandler = (cntr:UserAccessor) => async (ctx:Koa.Context,fail:
|
|||||||
return await checkRefreshAndUpdate();
|
return await checkRefreshAndUpdate();
|
||||||
} else throw e;
|
} else throw e;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
export const createRefreshTokenMiddleware = (knex:Knex)=> async (ctx:Koa.Context,next:Koa.Next)=>{
|
export const createRefreshTokenMiddleware = (cntr: UserAccessor) =>
|
||||||
const cntr= createKnexUserController(knex);
|
async (ctx: Koa.Context, next: Koa.Next) => {
|
||||||
const handler = refreshTokenHandler(cntr);
|
const handler = refreshTokenHandler(cntr);
|
||||||
const fail = async ()=>{
|
const fail = async () => {
|
||||||
const user = ctx.state.user as PayloadInfo;
|
const user = ctx.state.user as PayloadInfo;
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
refresh:false,
|
refresh: false,
|
||||||
...user
|
...user,
|
||||||
}
|
};
|
||||||
ctx.type = 'json';
|
ctx.type = "json";
|
||||||
};
|
};
|
||||||
const success = async ()=>{
|
const success = async () => {
|
||||||
const user = ctx.state.user as PayloadInfo;
|
const user = ctx.state.user as PayloadInfo;
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
...user,
|
...user,
|
||||||
refresh:true,
|
refresh: true,
|
||||||
refreshExpired: Math.floor(Date.now()/1000 + accessExpiredTime),
|
refreshExpired: Math.floor(Date.now() / 1000 + accessExpiredTime),
|
||||||
}
|
};
|
||||||
ctx.type = 'json';
|
ctx.type = "json";
|
||||||
|
};
|
||||||
|
await handler(ctx, fail, success);
|
||||||
|
};
|
||||||
|
export const resetPasswordMiddleware = (cntr: UserAccessor) =>
|
||||||
|
async (ctx:Koa.Context, next: Koa.Next) => {
|
||||||
|
const body = ctx.request.body;
|
||||||
|
if(typeof body !== "object" || !('username' in body)||!('oldpassword' in body) || !('newpassword' in body)){
|
||||||
|
return sendError(400,"request body is invalid format");
|
||||||
}
|
}
|
||||||
await handler(ctx,fail,success);
|
const username = body['username'];
|
||||||
|
const oldpw = body['oldpassword'];
|
||||||
|
const newpw = body['newpassword'];
|
||||||
|
const user = await cntr.findUser(username);
|
||||||
|
if(user === undefined){
|
||||||
|
return sendError(403,"not authorized");
|
||||||
|
}
|
||||||
|
if(!user.password.check_password(oldpw)){
|
||||||
|
return sendError(403,"not authorized");
|
||||||
|
}
|
||||||
|
user.reset_password(newpw);
|
||||||
|
ctx.body = {ok:true}
|
||||||
|
ctx.type = 'json';
|
||||||
}
|
}
|
||||||
export const getAdmin = async (knex: Knex) => {
|
export const getAdmin = async (cntr: UserAccessor) => {
|
||||||
const cntr = createKnexUserController(knex);
|
|
||||||
const admin = await cntr.findUser("admin");
|
const admin = await cntr.findUser("admin");
|
||||||
if (admin === undefined) {
|
if (admin === undefined) {
|
||||||
throw new Error("initial process failed!"); //???
|
throw new Error("initial process failed!"); //???
|
||||||
|
189
src/server.ts
189
src/server.ts
@ -1,101 +1,126 @@
|
|||||||
import Koa from 'koa';
|
import Koa from 'koa';
|
||||||
import Router from 'koa-router';
|
import Router from 'koa-router';
|
||||||
|
|
||||||
import {get_setting} from './SettingConfig';
|
import {get_setting, SettingConfig} from './SettingConfig';
|
||||||
import {connectDB} from './database';
|
import {connectDB} from './database';
|
||||||
import {DiffManager, createDiffRouter} from './diff/mod';
|
import {DiffManager, createDiffRouter} from './diff/mod';
|
||||||
|
|
||||||
import { createReadStream, readFileSync } from 'fs';
|
import { createReadStream, readFileSync } from 'fs';
|
||||||
import getContentRouter from './route/contents';
|
import getContentRouter from './route/contents';
|
||||||
import { createKnexDocumentAccessor } from './db/mod';
|
import { createKnexDocumentAccessor, createKnexUserController } from './db/mod';
|
||||||
import bodyparser from 'koa-bodyparser';
|
import bodyparser from 'koa-bodyparser';
|
||||||
import {error_handler} from './route/error_handler';
|
import {error_handler} from './route/error_handler';
|
||||||
import {createUserMiddleWare,createLoginMiddleware, isAdminFirst, getAdmin, LogoutMiddleware, createRefreshTokenMiddleware} from './login';
|
import {createUserMiddleWare,createLoginMiddleware, isAdminFirst, getAdmin, LogoutMiddleware, createRefreshTokenMiddleware} from './login';
|
||||||
|
|
||||||
import {createInterface as createReadlineInterface} from 'readline';
|
import {createInterface as createReadlineInterface} from 'readline';
|
||||||
|
import { DocumentAccessor, UserAccessor } from './model/mod';
|
||||||
|
|
||||||
|
class ServerApplication{
|
||||||
|
readonly userController: UserAccessor;
|
||||||
|
readonly documentController: DocumentAccessor;
|
||||||
|
readonly diffManger;
|
||||||
|
readonly app: Koa;
|
||||||
|
private index_html:Buffer;
|
||||||
|
constructor(userController: UserAccessor,documentController:DocumentAccessor){
|
||||||
|
this.userController = userController;
|
||||||
|
this.documentController = documentController;
|
||||||
|
this.diffManger = new DiffManager(documentController);
|
||||||
|
this.app = new Koa();
|
||||||
|
this.index_html = readFileSync("index.html");
|
||||||
|
}
|
||||||
|
private async setup(){
|
||||||
|
const setting = get_setting();
|
||||||
|
const app = this.app;
|
||||||
|
|
||||||
|
if(setting.cli){
|
||||||
|
const userAdmin = await getAdmin(this.userController);
|
||||||
|
if(await isAdminFirst(userAdmin)){
|
||||||
|
const rl = createReadlineInterface({input:process.stdin,output:process.stdout});
|
||||||
|
rl.setPrompt("put admin password : ");
|
||||||
|
rl.prompt();
|
||||||
|
const pw = await new Promise((res:(data:string)=>void,err)=>{
|
||||||
|
rl.on('line',(data)=>res(data));
|
||||||
|
});
|
||||||
|
userAdmin.reset_password(pw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.use(bodyparser());
|
||||||
|
app.use(error_handler);
|
||||||
|
app.use(createUserMiddleWare(this.userController));
|
||||||
|
|
||||||
|
let diff_router = createDiffRouter(this.diffManger);
|
||||||
|
this.diffManger.register("manga","testdata");
|
||||||
|
const index_html = readFileSync("index.html");
|
||||||
|
let router = new Router();
|
||||||
|
|
||||||
|
router.use('/api/diff',diff_router.routes());
|
||||||
|
router.use('/api/diff',diff_router.allowedMethods());
|
||||||
|
|
||||||
|
this.serve_index(router);
|
||||||
|
this.serve_static_file(router);
|
||||||
|
|
||||||
|
const content_router = getContentRouter(this.documentController);
|
||||||
|
router.use('/api/doc',content_router.routes());
|
||||||
|
router.use('/api/doc',content_router.allowedMethods());
|
||||||
|
|
||||||
|
router.post('/user/login',createLoginMiddleware(this.userController));
|
||||||
|
router.post('/user/logout',LogoutMiddleware);
|
||||||
|
router.post('/user/refresh',createRefreshTokenMiddleware(this.userController));
|
||||||
|
|
||||||
|
if(setting.mode == "development"){
|
||||||
|
let mm_count = 0;
|
||||||
|
app.use(async (ctx,next)=>{
|
||||||
|
console.log(`==========================${mm_count++}`);
|
||||||
|
const fromClient = ctx.state['user'].username === "" ? ctx.ip : ctx.state['user'].username;
|
||||||
|
console.log(`${fromClient} : ${ctx.method} ${ctx.url}`);
|
||||||
|
await next();
|
||||||
|
//console.log(`404`);
|
||||||
|
});}
|
||||||
|
app.use(router.routes());
|
||||||
|
app.use(router.allowedMethods());
|
||||||
|
}
|
||||||
|
private serve_index(router:Router){
|
||||||
|
const serveindex = (url:string)=>{
|
||||||
|
router.get(url, (ctx)=>{ctx.type = 'html'; ctx.body = this.index_html;})
|
||||||
|
}
|
||||||
|
serveindex('/');
|
||||||
|
serveindex('/doc/:rest(.*)');
|
||||||
|
serveindex('/search');
|
||||||
|
serveindex('/login');
|
||||||
|
serveindex('/profile');
|
||||||
|
serveindex('/difference');
|
||||||
|
}
|
||||||
|
private serve_static_file(router: Router){
|
||||||
|
const setting = get_setting();
|
||||||
|
const static_file_server = (path:string,type:string) => {
|
||||||
|
router.get('/'+path,async (ctx,next)=>{
|
||||||
|
ctx.type = type; ctx.body = createReadStream(path);
|
||||||
|
})}
|
||||||
|
static_file_server('dist/css/style.css','css');
|
||||||
|
static_file_server('dist/js/bundle.js','js');
|
||||||
|
if(setting.mode === "development")
|
||||||
|
static_file_server('dist/js/bundle.js.map','text');
|
||||||
|
}
|
||||||
|
start_server(){
|
||||||
|
let setting = get_setting();
|
||||||
|
console.log("start server");
|
||||||
|
//todo : support https
|
||||||
|
return this.app.listen(setting.port,setting.localmode ? "127.0.0.1" : "0.0.0.0");
|
||||||
|
}
|
||||||
|
static async createServer(){
|
||||||
|
const setting = get_setting();
|
||||||
|
let db = await connectDB();
|
||||||
|
|
||||||
|
const app = new ServerApplication(createKnexUserController(db)
|
||||||
|
,createKnexDocumentAccessor(db));
|
||||||
|
await app.setup();
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
//let Koa = require("koa");
|
//let Koa = require("koa");
|
||||||
|
|
||||||
export async function create_server(){
|
export async function create_server(){
|
||||||
const setting = get_setting();
|
return await ServerApplication.createServer();
|
||||||
let db = await connectDB();
|
|
||||||
|
|
||||||
let diffmgr = new DiffManager(createKnexDocumentAccessor(db));
|
|
||||||
let diff_router = createDiffRouter(diffmgr);
|
|
||||||
diffmgr.register("manga","testdata");
|
|
||||||
|
|
||||||
if(setting.cli){
|
|
||||||
const userAdmin = await getAdmin(db);
|
|
||||||
if(await isAdminFirst(userAdmin)){
|
|
||||||
const rl = createReadlineInterface({input:process.stdin,output:process.stdout});
|
|
||||||
rl.setPrompt("put admin password : ");
|
|
||||||
rl.prompt();
|
|
||||||
const pw = await new Promise((res:(data:string)=>void,err)=>{
|
|
||||||
rl.on('line',(data)=>res(data));
|
|
||||||
});
|
|
||||||
userAdmin.reset_password(pw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let app = new Koa();
|
|
||||||
app.use(bodyparser());
|
|
||||||
app.use(error_handler);
|
|
||||||
app.use(createUserMiddleWare(db));
|
|
||||||
//app.use(ctx=>{ctx.state['setting'] = settings});
|
|
||||||
|
|
||||||
|
|
||||||
const index_html = readFileSync("index.html");
|
|
||||||
let router = new Router();
|
|
||||||
|
|
||||||
router.use('/api/diff',diff_router.routes());
|
|
||||||
router.use('/api/diff',diff_router.allowedMethods());
|
|
||||||
|
|
||||||
//let watcher = new Watcher(setting.path[0]);
|
|
||||||
//await watcher.setup([]);
|
|
||||||
const serveindex = (url:string)=>{
|
|
||||||
router.get(url, (ctx)=>{ctx.type = 'html'; ctx.body = index_html;})
|
|
||||||
}
|
|
||||||
serveindex('/');
|
|
||||||
serveindex('/doc/:rest(.*)');
|
|
||||||
serveindex('/search');
|
|
||||||
serveindex('/login');
|
|
||||||
serveindex('/profile');
|
|
||||||
serveindex('/difference');
|
|
||||||
|
|
||||||
const static_file_server = (path:string,type:string) => {
|
|
||||||
router.get('/'+path,async (ctx,next)=>{
|
|
||||||
ctx.type = type; ctx.body = createReadStream(path);
|
|
||||||
})}
|
|
||||||
static_file_server('dist/css/style.css','css');
|
|
||||||
static_file_server('dist/js/bundle.js','js');
|
|
||||||
if(setting.mode === "development")
|
|
||||||
static_file_server('dist/js/bundle.js.map','text');
|
|
||||||
|
|
||||||
const content_router = getContentRouter(createKnexDocumentAccessor(db));
|
|
||||||
router.use('/api/doc',content_router.routes());
|
|
||||||
router.use('/api/doc',content_router.allowedMethods());
|
|
||||||
|
|
||||||
router.post('/user/login',createLoginMiddleware(db));
|
|
||||||
router.post('/user/logout',LogoutMiddleware);
|
|
||||||
router.post('/user/refresh',createRefreshTokenMiddleware(db));
|
|
||||||
|
|
||||||
if(setting.mode == "development"){
|
|
||||||
let mm_count = 0;
|
|
||||||
app.use(async (ctx,next)=>{
|
|
||||||
console.log(`==========================${mm_count++}`);
|
|
||||||
const fromClient = ctx.state['user'].username === "" ? ctx.ip : ctx.state['user'].username;
|
|
||||||
console.log(`${fromClient} : ${ctx.method} ${ctx.url}`);
|
|
||||||
await next();
|
|
||||||
//console.log(`404`);
|
|
||||||
});}
|
|
||||||
app.use(router.routes());
|
|
||||||
app.use(router.allowedMethods());
|
|
||||||
return app;
|
|
||||||
}
|
}
|
||||||
export const start_server = (server: Koa)=>{
|
|
||||||
let setting = get_setting();
|
export default {create_server};
|
||||||
console.log("start server");
|
|
||||||
//todo : support https
|
|
||||||
return server.listen(setting.port,setting.localmode ? "127.0.0.1" : "0.0.0.0");
|
|
||||||
}
|
|
||||||
export default {create_server, start_server};
|
|
Loading…
Reference in New Issue
Block a user