Browse Source

typings

main
Nikky 4 years ago
parent
commit
e596bddb27
  1. 4
      src/index.js
  2. 22
      src/logic/cache.js
  3. 14
      src/logic/session.js
  4. 2
      src/logic/utils.js
  5. 5
      src/model/model.d.ts
  6. 13
      src/model/user.model.js
  7. 25
      src/route/auth.controller.js
  8. 7
      src/route/route.d.ts
  9. 7
      src/route/user.controller.js
  10. 7
      src/type/database.d.ts
  11. 6
      src/type/webserver.d.ts

4
src/index.js

@ -15,8 +15,8 @@ async function Database(){
const opts = {db}; const opts = {db};
UserEntity(opts); UserEntity(opts);
} }
await db.authenticate(); await db.authenticate(); //connect to the database of choice
await db.sync({alter: true}); await db.sync({alter: true}); //add missing tables and columns
} }
async function WebApp(){ async function WebApp(){

22
src/logic/cache.js

@ -20,12 +20,12 @@ export class CacheTable{
this.entries[key] = val; this.entries[key] = val;
return val; return val;
} }
remove(key){ remove(key){
if(this.entries[key] !== undefined){ if(this.entries[key] !== undefined){
delete this.entries[key]; delete this.entries[key];
this.count--; this.count--;
} }
} }
get(key){ return this.entries[key]; } get(key){ return this.entries[key]; }
allEntries(){ return this.entries; } allEntries(){ return this.entries; }
} }
@ -37,11 +37,11 @@ export class SpamCache extends CacheTable{
super(1024); super(1024);
} }
/** /**
* @param string key * @param string key
* @param {[[maxHits: number, durationMs: number]]} constraints * @param {[[maxHits: number, durationMs: number]]} constraints
* @returns * @returns
*/ */
check(key, constraints){ check(key, constraints){
const now = Date.now(); const now = Date.now();
let record = this.get(key); let record = this.get(key);

14
src/logic/session.js

@ -1,12 +1,12 @@
import { CacheTable, SpamCache } from "./cache.js"; import { CacheTable, SpamCache } from "./cache.js";
import { requestIp } from "./utils.js"; import { ipAddress } from "./utils.js";
export class UserSession{ export class UserSession{
constructor(user, request){ constructor(user, request){
this.user = user; this.user = user;
this.createdAt = Date.now(); this.createdAt = Date.now();
this.ip = requestIp(request); this.ip = ipAddress(request);
this.spam = new SpamCache(); this.spam = new SpamCache();
userCache.set(user.token, this); userCache.set(user.token, this);
} }
@ -18,6 +18,16 @@ export class UserSession{
static find(token){ static find(token){
return userCache.get(token); return userCache.get(token);
} }
static onUpdate(user){
//todo: figure out where exactly
//this hook is necessary, if it is
const session = find(user);
if(session) session.user = user;
}
static onDestroy(user){
const session = find(user);
if(session) session.kill();
}
} }
const userCache = new CacheTable(8192); const userCache = new CacheTable(8192);

2
src/logic/utils.js

@ -12,7 +12,7 @@ export function errorOut(reply, msg, code){
reply.send(msg || 'Bad request.'); reply.send(msg || 'Bad request.');
} }
export function requestIp(request){ export function ipAddress(request){
return request.ip; return request.ip;
} }

5
src/model/model.d.ts

@ -0,0 +1,5 @@
import { database } from '../type/database';
export interface props{
db: database
};

13
src/model/user.model.js

@ -1,9 +1,8 @@
import Sequelize from 'sequelize'; import Sequelize from 'sequelize';
import { UserSession } from '../logic/session.js';
/** @param {import('./model').props} */
/**
* @param {Object} props
* @param {import('sequelize/types').Sequelize} props.db
*/
const UserEntity = ({db}) => ( const UserEntity = ({db}) => (
db.define('Users', { db.define('Users', {
@ -24,7 +23,11 @@ const UserEntity = ({db}) => (
indexes: [ indexes: [
{ fields: ['token'], unique: true }, { fields: ['token'], unique: true },
{ fields: ['email'], unique: true } { fields: ['email'], unique: true }
] ],
hooks: {
beforeUpdate: UserSession.onUpdate,
afterDestroy: UserSession.onDestroy
}
}) })
); );

25
src/route/auth.controller.js

@ -1,22 +1,21 @@
import { checkStringParam, errorOut, notYet, randomElement, requestIp, reverseString, hours, minutes } from '../logic/utils.js'; import { checkStringParam, errorOut, notYet, randomElement, ipAddress, reverseString, hours, minutes } from '../logic/utils.js';
import { Animals } from '../misc/animals.js'; import { Animals } from '../misc/animals.js';
import { reissueToken, generateToken, newTokenExpiry, hashPassword, doesPasswordMatch, isEndpointAllowedForBannedUsers, isEndpointProtected, generateRestoreCode, restoreValidity, restoreAttempts } from '../logic/security.js'; import { reissueToken, generateToken, newTokenExpiry, hashPassword, doesPasswordMatch, isEndpointAllowedForBannedUsers, isEndpointProtected, generateRestoreCode, restoreValidity, restoreAttempts } from '../logic/security.js';
import { sendRestorationLink } from '../logic/email.js'; import { sendRestorationLink } from '../logic/email.js';
import { UserSession } from '../logic/session.js'; import { UserSession } from '../logic/session.js';
import { SpamCache } from '../logic/cache.js'; import { SpamCache } from '../logic/cache.js';
/** /** @param {import('./route').props} */
* @param {Object} props
* @param {import('fastify').FastifyInstance} props.app
* @param {import('sequelize/types').Sequelize} props.db
*/
function AuthController({app, db}){ function AuthController({app, db}){
const { Users } = db.models; const { Users } = db.models;
const signInSpam = new SpamCache(); const spamCheck = {
const signUpSpam = new SpamCache(); signIn: new SpamCache(),
const restoreApplySpam = new SpamCache(); signUp: new SpamCache(),
restoreApply: new SpamCache()
};
{ //validate token header and put .session in every request { //validate token header and put .session in every request
app.decorateRequest('session', null); app.decorateRequest('session', null);
@ -45,7 +44,7 @@ function AuthController({app, db}){
app.post('/auth/sign-in', async (request, reply) => { app.post('/auth/sign-in', async (request, reply) => {
const {email, paswd} = request.body || {}; const {email, paswd} = request.body || {};
if(signInSpam.check(requestIp(request), [[5000, 2*hours]])){ if(spamCheck.signIn.check(ipAddress(request), [[5000, 2*hours]])){
return errorOut(reply, 'error.too_fast'); return errorOut(reply, 'error.too_fast');
} }
@ -70,7 +69,7 @@ function AuthController({app, db}){
app.post('/auth/sign-up', async (request, reply) => { app.post('/auth/sign-up', async (request, reply) => {
const {email, username, paswd} = request.body || {}; const {email, username, paswd} = request.body || {};
if(signUpSpam.check(requestIp(request), [[5000, 2*hours], [100, 10*minutes]])){ if(spamCheck.signUp.check(ipAddress(request), [[5000, 2*hours], [100, 10*minutes]])){
return errorOut(reply, 'error.too_fast'); return errorOut(reply, 'error.too_fast');
} }
@ -101,7 +100,7 @@ function AuthController({app, db}){
tokenExpiry: newTokenExpiry(), tokenExpiry: newTokenExpiry(),
paswd: hashPassword(reverseString(paswd)), paswd: hashPassword(reverseString(paswd)),
role: 'user', role: 'user',
firstIp: requestIp(request) firstIp: ipAddress(request)
}; };
await Users.create(newUser); await Users.create(newUser);
return {token: newUser.token}; return {token: newUser.token};
@ -130,7 +129,7 @@ function AuthController({app, db}){
const {email, code, newpaswd} = request.body || {}; const {email, code, newpaswd} = request.body || {};
const changeRequested = (newpaswd != null); const changeRequested = (newpaswd != null);
if(restoreApplySpam.check(requestIp(request), [[100, 12*hours], [25, 30*minutes]])){ if(spamCheck.restoreApply.check(ipAddress(request), [[100, 12*hours], [25, 30*minutes]])){
return errorOut(reply, 'error.too_fast'); return errorOut(reply, 'error.too_fast');
} }

7
src/route/route.d.ts

@ -0,0 +1,7 @@
import { webserver } from '../type/webserver';
import { database } from '../type/database';
export interface props{
app: webserver,
db: database
};

7
src/route/user.controller.js

@ -1,10 +1,7 @@
import { reissueToken, tokenLifetime, tokenReissue } from '../logic/security.js'; import { reissueToken, tokenLifetime, tokenReissue } from '../logic/security.js';
/** /** @param {import('./route').props} */
* @param {Object} props
* @param {import('fastify').FastifyInstance} props.app
* @param {import('sequelize/types').Sequelize} props.db
*/
function UserController({app, db}){ function UserController({app, db}){
const { Users } = db.models; const { Users } = db.models;

7
src/type/database.d.ts

@ -0,0 +1,7 @@
import { Sequelize } from 'sequelize/types';
export type database = Sequelize & {
models: {
potato: string
}
};

6
src/type/webserver.d.ts

@ -0,0 +1,6 @@
import { FastifyInstance } from 'fastify/types/instance';
import { UserSession } from '../logic/session.js';
export type webserver = FastifyInstance & {
session: UserSession
};
Loading…
Cancel
Save