Commit 5799ae7c authored by nanahira's avatar nanahira

rework

parent 4df46f05
let config = process.env['NODE_ENV'] == 'development' ? require('./conf-dev').default : { let config = process.env['NODE_ENV'] == 'development' ? require('./conf-dev').default : {
DATABASE: process.env['DATABASE'], DATABASE: process.env['DATABASE'],
synchronize: !process.env['DB_NO_SYNC'],
Mail: { Mail: {
SMTP_HOST: process.env['SMTP_HOST'], SMTP_HOST: process.env['SMTP_HOST'],
SMTP_USERNAME: process.env['SMTP_USERNAME'], SMTP_USERNAME: process.env['SMTP_USERNAME'],
......
This diff is collapsed.
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
"log4js": "^1.1.1", "log4js": "^1.1.1",
"mime": "^1.3.4", "mime": "^1.3.4",
"nodemailer": "^3.1.8", "nodemailer": "^3.1.8",
"pg": "^6.1.5", "pg": "^8.7.1",
"typeorm": "^0.0.11", "typeorm": "^0.2.37",
"uuid": "^3.0.1" "uuid": "^3.0.1"
}, },
"devDependencies": { "devDependencies": {
......
...@@ -7,6 +7,7 @@ import privateRouter from './src/privateRoutes'; ...@@ -7,6 +7,7 @@ import privateRouter from './src/privateRoutes';
import { createConnection } from 'typeorm'; import { createConnection } from 'typeorm';
import config from './config'; import config from './config';
import {Token, User, UserNameChangeHistory} from './src/model'; import {Token, User, UserNameChangeHistory} from './src/model';
import { setConnection } from './src/controllers/entity-manager';
const app = new Koa(); const app = new Koa();
...@@ -65,18 +66,17 @@ app.use(privateRouter.allowedMethods()); ...@@ -65,18 +66,17 @@ app.use(privateRouter.allowedMethods());
async function main() { async function main() {
console.log('Creating database connection.'); console.log('Creating database connection.');
try { try {
await createConnection({ const conn = await createConnection({
driver: { type: 'postgres',
type: 'postgres', url: config.DATABASE,
url: config.DATABASE
},
entities: [User, Token, UserNameChangeHistory], entities: [User, Token, UserNameChangeHistory],
autoSchemaSync: true, synchronize: config.synchronize,
logging: { /*logging: {
logQueries: process.env['NODE_ENV'] === 'development', logQueries: process.env['NODE_ENV'] === 'development',
logFailedQueryError: process.env['NODE_ENV'] === 'development', logFailedQueryError: process.env['NODE_ENV'] === 'development',
} }*/
}); });
setConnection(conn);
console.log('Starting server.'); console.log('Starting server.');
app.listen(3000, () => { app.listen(3000, () => {
console.log('Server is running at port %s', 3000); console.log('Server is running at port %s', 3000);
......
import { Context } from 'koa'; import { Context } from 'koa';
import { SignIn, SignUp, Token, User } from '../model'; import { SignIn, SignUp, Token, User } from '../model';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import { getEntityManager } from 'typeorm'; import { getEntityManager } from './entity-manager';
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import tp from '../mail'; import tp from '../mail';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
...@@ -95,7 +95,7 @@ export const signup = async (ctx: Context) => { ...@@ -95,7 +95,7 @@ export const signup = async (ctx: Context) => {
ip_address: ctx.request.ip ip_address: ctx.request.ip
}); });
const user = await getEntityManager().persist(newUser); const user = await getEntityManager().save(newUser);
const key = uuid.v1(); const key = uuid.v1();
let _token: Token = new Token({ let _token: Token = new Token({
...@@ -105,7 +105,7 @@ export const signup = async (ctx: Context) => { ...@@ -105,7 +105,7 @@ export const signup = async (ctx: Context) => {
type: 'activate' type: 'activate'
}); });
await getEntityManager().persist(_token); await getEntityManager().save(_token);
const url = new URL('https://accounts.moecube.com/activate'); const url = new URL('https://accounts.moecube.com/activate');
url.searchParams.set('key', key); url.searchParams.set('key', key);
...@@ -117,7 +117,7 @@ export const signup = async (ctx: Context) => { ...@@ -117,7 +117,7 @@ export const signup = async (ctx: Context) => {
text: `单击链接 或将链接复制到网页地址栏并回车 来激活账号 ${url}`, text: `单击链接 或将链接复制到网页地址栏并回车 来激活账号 ${url}`,
html: views.activate({ locale: 'zh-CN', username: user.username, url }) html: views.activate({ locale: 'zh-CN', username: user.username, url })
}).catch(function(error) { }).catch(function(error) {
console.log(`Failed to send mail to ${user.username}<${user.email}>`); console.log(`Failed to send mail to ${user.username}<${user.email}>: ${error.toString()}`);
}); });
const token = createToken({ const token = createToken({
...@@ -160,7 +160,7 @@ export const forgot = async (ctx: Context) => { ...@@ -160,7 +160,7 @@ export const forgot = async (ctx: Context) => {
}); });
await getEntityManager().persist(token); await getEntityManager().save(token);
const url = new URL('https://accounts.moecube.com/reset'); const url = new URL('https://accounts.moecube.com/reset');
url.searchParams.set('key', key); url.searchParams.set('key', key);
...@@ -194,7 +194,7 @@ export const resetPassword = async (ctx: Context) => { ...@@ -194,7 +194,7 @@ export const resetPassword = async (ctx: Context) => {
} }
const userRep = getEntityManager().getRepository(User); const userRep = getEntityManager().getRepository(User);
let user: User | undefined = await userRep.findOneById(u.user_id); let user: User | undefined = await userRep.findOne({where: {id: u.user_id}});
if (!user) { if (!user) {
ctx.throw('i_user_unexists', 400); ctx.throw('i_user_unexists', 400);
...@@ -206,7 +206,7 @@ export const resetPassword = async (ctx: Context) => { ...@@ -206,7 +206,7 @@ export const resetPassword = async (ctx: Context) => {
user.password_hash = (await Bluebird.promisify(crypto.pbkdf2)(u.password, salt, 64000, 32, 'sha256')).toString('hex'); user.password_hash = (await Bluebird.promisify(crypto.pbkdf2)(u.password, salt, 64000, 32, 'sha256')).toString('hex');
user.salt = salt; user.salt = salt;
ctx.body = await getEntityManager().persist(user); ctx.body = await getEntityManager().save(user);
await tokenReq.remove(token); await tokenReq.remove(token);
...@@ -235,7 +235,7 @@ export const activate = async (ctx: Context) => { ...@@ -235,7 +235,7 @@ export const activate = async (ctx: Context) => {
user.active = true; user.active = true;
user.email = token.data; user.email = token.data;
ctx.body = await userReq.persist(user); ctx.body = await userReq.save(user);
let tokens: Token[] = await tokenReq.find({ user_id: user.id, type: 'activate' }); let tokens: Token[] = await tokenReq.find({ user_id: user.id, type: 'activate' });
...@@ -249,5 +249,9 @@ export const authUser = async (ctx: Context) => { ...@@ -249,5 +249,9 @@ export const authUser = async (ctx: Context) => {
const userReq = getEntityManager().getRepository(User); const userReq = getEntityManager().getRepository(User);
ctx.status = 200; ctx.status = 200;
ctx.body = await userReq.findOne({ id: user.id }); const gotUser = await userReq.findOne({ id: user.id });
}; if (gotUser) {
\ No newline at end of file gotUser.cleanSensitiveData()
}
ctx.body = gotUser;
};
import { Connection } from "typeorm"
let connection: Connection;
export function setConnection(conn: Connection) {
connection = conn;
}
export function getEntityManager() {
return connection.manager;
}
...@@ -2,7 +2,7 @@ import { Context } from 'koa'; ...@@ -2,7 +2,7 @@ import { Context } from 'koa';
import {Token, User, UserNameChangeHistory} from '../model'; import {Token, User, UserNameChangeHistory} from '../model';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import { getEntityManager } from 'typeorm'; import { getEntityManager } from './entity-manager';
import tp from '../mail'; import tp from '../mail';
import config from '../../config'; import config from '../../config';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
...@@ -42,7 +42,7 @@ export const checkUserExists = async (ctx: Context) => { ...@@ -42,7 +42,7 @@ export const checkUserExists = async (ctx: Context) => {
if (user) { if (user) {
ctx.body = user; ctx.body = user.cleanSensitiveData();
} else { } else {
ctx.throw('i_not_found', 400); ctx.throw('i_not_found', 400);
} }
...@@ -76,10 +76,10 @@ export const UpdateProfiles = async (ctx: Context) => { ...@@ -76,10 +76,10 @@ export const UpdateProfiles = async (ctx: Context) => {
Object.assign(_user, ctx.request.body); Object.assign(_user, ctx.request.body);
await getEntityManager().persist(_user); await getEntityManager().save(_user);
ctx.status = 200; ctx.status = 200;
ctx.body = _user; ctx.body = _user.cleanSensitiveData();
}; };
...@@ -137,7 +137,7 @@ export const UpdateAccount = async (ctx: Context) => { ...@@ -137,7 +137,7 @@ export const UpdateAccount = async (ctx: Context) => {
if (u.username != user.username) { if (u.username != user.username) {
const historyRep = getEntityManager().getRepository(UserNameChangeHistory); const historyRep = getEntityManager().getRepository(UserNameChangeHistory);
let changeHistory = new UserNameChangeHistory(user.username, u.username, u.user_id); let changeHistory = new UserNameChangeHistory(user.username, u.username, u.user_id);
historyRep.persist(changeHistory); historyRep.save(changeHistory);
} }
user.username = u.username; user.username = u.username;
...@@ -164,7 +164,7 @@ export const UpdateAccount = async (ctx: Context) => { ...@@ -164,7 +164,7 @@ export const UpdateAccount = async (ctx: Context) => {
type: 'activate', type: 'activate',
}); });
await getEntityManager().persist(token); await getEntityManager().save(token);
const url = new URL('https://accounts.moecube.com/activate'); const url = new URL('https://accounts.moecube.com/activate');
url.searchParams.set('key', key); url.searchParams.set('key', key);
...@@ -184,7 +184,7 @@ export const UpdateAccount = async (ctx: Context) => { ...@@ -184,7 +184,7 @@ export const UpdateAccount = async (ctx: Context) => {
} }
ctx.status = 200; ctx.status = 200;
ctx.body = await userRep.persist(user); ctx.body = (await userRep.save(user)).cleanSensitiveData();
}; };
...@@ -194,6 +194,7 @@ export const legacyYGOProAuth = async (ctx: Context) => { ...@@ -194,6 +194,7 @@ export const legacyYGOProAuth = async (ctx: Context) => {
if (!user) { if (!user) {
return ctx.throw(404); return ctx.throw(404);
} }
user.cleanSensitiveData();
ctx.body = { user }; ctx.body = { user };
}; };
......
import { Column, CreateDateColumn, Entity, PrimaryColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; import { Column, CreateDateColumn, Entity, PrimaryColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import { ColumnTypes } from 'typeorm/metadata/types/ColumnTypes';
import { URL } from 'url'; import { URL } from 'url';
@Entity('users') @Entity('users')
export class User { export class User {
@PrimaryGeneratedColumn(ColumnTypes.INTEGER) @PrimaryGeneratedColumn({type: 'int4'})
id: number; id: number;
@Column(ColumnTypes.STRING, { unique: true, nullable: false }) @Column('varchar', { length: 255, unique: true, nullable: false })
username: string; username: string;
@Column(ColumnTypes.STRING, { nullable: true }) @Column('varchar', { length: 255, nullable: true })
name?: string; name?: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
email: string; email: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
password_hash: string; password_hash: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
salt: string; salt: string;
@Column(ColumnTypes.BOOLEAN, { nullable: false }) @Column('boolean', { nullable: false })
active: boolean; active: boolean;
@Column(ColumnTypes.BOOLEAN, { nullable: false }) @Column('boolean', { nullable: false })
admin: boolean; admin: boolean;
@Column(ColumnTypes.STRING, { nullable: true }) @Column('varchar', { length: 255, nullable: true })
avatar?: string; avatar?: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
locale: string; locale: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
registration_ip_address: string; registration_ip_address: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
ip_address: string; ip_address: string;
@CreateDateColumn({ nullable: false }) @CreateDateColumn({ nullable: false })
created_at: Date; created_at: Date;
...@@ -57,6 +56,15 @@ export class User { ...@@ -57,6 +56,15 @@ export class User {
return 'https://cdn01.moecube.com/accounts/default_avatar.jpg'; return 'https://cdn01.moecube.com/accounts/default_avatar.jpg';
} }
} }
cleanSensitiveData() {
// this.email = '_masked';
this.password_hash = '_masked';
this.salt = '_masked';
this.registration_ip_address = '_masked';
this.ip_address = '_masked';
return this;
}
} }
interface UserCreate { interface UserCreate {
...@@ -74,13 +82,13 @@ interface UserCreate { ...@@ -74,13 +82,13 @@ interface UserCreate {
@Entity('tokens') @Entity('tokens')
export class Token { export class Token {
@PrimaryColumn(ColumnTypes.STRING) @PrimaryColumn('varchar', { length: 255 })
key: string; key: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
user_id: number; user_id: number;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
type: string; type: string;
@Column(ColumnTypes.STRING, { nullable: false }) @Column('varchar', { length: 255, nullable: false })
data: string; data: string;
constructor(props: Token) { constructor(props: Token) {
...@@ -112,13 +120,13 @@ export interface SignUp { ...@@ -112,13 +120,13 @@ export interface SignUp {
@Entity('username_change_history') @Entity('username_change_history')
export class UserNameChangeHistory { export class UserNameChangeHistory {
@PrimaryGeneratedColumn(ColumnTypes.INTEGER) @PrimaryGeneratedColumn({type: 'int4'})
id: number; id: number;
@Column(ColumnTypes.INTEGER) @Column('int4')
userid: number; userid: number;
@Column(ColumnTypes.STRING) @Column('varchar', { length: 255 })
old_username: string; old_username: string;
@Column(ColumnTypes.STRING) @Column('varchar', { length: 255 })
new_username: string; new_username: string;
@UpdateDateColumn() @UpdateDateColumn()
change_time: Date; change_time: Date;
...@@ -130,4 +138,4 @@ export class UserNameChangeHistory { ...@@ -130,4 +138,4 @@ export class UserNameChangeHistory {
this.change_time = new Date(); this.change_time = new Date();
} }
} }
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment