Skip to content

Commit

Permalink
Merge pull request #27 from inu-appcenter/feature-test-account
Browse files Browse the repository at this point in the history
Feature test account
  • Loading branch information
potados99 authored Apr 24, 2020
2 parents 253440d + 0b4e87a commit 850b9fc
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 59 deletions.
2 changes: 1 addition & 1 deletion config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default {
expiresIn: '24h',
cookie_options: {
encoding: 'none', // we already used JWT to encode
isSecure: true, // https only?
isSecure: false, // https only?
isHttpOnly: true, // prevent client alteration
clearInvalid: true, // remove invalid cookies
strictHeader: true, // don't allow violations of RFC 6265
Expand Down
16 changes: 10 additions & 6 deletions lib/common/di/modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ import UserService from '../../domain/services/UserService';
import sequelize from '../../infrastructure/database/sequelize';
import TransactionService from '../../domain/services/TransactionService';
import Sequelize from 'sequelize';
import UserRemoteDataSource from '../../domain/repositories/UserRemoteDataSource';
import UserRemoteDataSourceImpl from '../../interfaces/storage/UserRemoteDataSourceImpl';
import CafeteriaRemoteDataSourceImpl from '../../interfaces/storage/CafeteriaRemoteDataSourceImpl';
import CafeteriaRemoteDataSource from '../../domain/repositories/CafeteriaRemoteDataSource';
import UserRemoteDataSource from '../../interfaces/storage/UserRemoteDataSource';
import UserLocalDataSource from '../../interfaces/storage/UserLocalDataSource';
import CafeteriaRemoteDataSource from '../../interfaces/storage/CafeteriaRemoteDataSource';

export default [
/**
Expand Down Expand Up @@ -180,6 +179,7 @@ export default [
{
create: async (r) => new UserRepositoryImpl({
db: await r(Sequelize),
localDataSource: await r(UserLocalDataSource),
remoteDataSource: await r(UserRemoteDataSource),
}),
as: UserRepository,
Expand All @@ -195,11 +195,15 @@ export default [
* Data Sources
*/
{
create: async (r) => new CafeteriaRemoteDataSourceImpl(),
create: async (r) => new CafeteriaRemoteDataSource(),
as: CafeteriaRemoteDataSource,
},
{
create: async (r) => new UserRemoteDataSourceImpl(),
create: async (r) => new UserLocalDataSource(),
as: UserLocalDataSource,
},
{
create: async (r) => new UserRemoteDataSource(),
as: UserRemoteDataSource,
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

class CafeteriaRemoteDataSource {
class CafeteriaDataSource {
fetchRawMenus() {
throw new Error('Not implemented!');
}
}

export default CafeteriaRemoteDataSource;
export default CafeteriaDataSource;
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

class UserRemoteDataSource {
class UserDataSource {
userExists(id) {
throw new Error('Not implemented!');
}

fetchLoginResult(id, password) {
throw new Error('Not implemented!');
}
}

export default UserRemoteDataSource;
export default UserDataSource;
2 changes: 1 addition & 1 deletion lib/domain/repositories/UserRepository.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

class UserRepository {
getRemoteLoginResult(id, password) {
getLoginResult(id, password) {
throw new Error('Not implemented!');
}

Expand Down
2 changes: 1 addition & 1 deletion lib/domain/services/UserService.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class UserService {
}

async _loginWithIdAndPassword(id, password) {
const remoteLoginResult = await this.userRepository.getRemoteLoginResult(id, password);
const remoteLoginResult = await this.userRepository.getLoginResult(id, password);

const isSucceeded = (remoteLoginResult === RemoteLoginResult.SUCCESS);
if (isSucceeded) {
Expand Down
2 changes: 1 addition & 1 deletion lib/infrastructure/webserver/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async function registerPlugins(server) {
plugin: HapiSwagger,
options: {
host: config.server.host,
schemes: ['https'],
schemes: ['http', 'https'],
info: {
title: '카페테리아 서버 API',
version: thisPackage.version,
Expand Down
11 changes: 5 additions & 6 deletions lib/interfaces/controllers/UserController.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,13 @@ class LoginHandler {
}

_successfulResponse(body, jwt) {
return this._h
.response(body)
.state('token', jwt, config.auth.cookie_options) // cookie
.header('Authorization', jwt); // header
return this._h.response(body)
.header('Authorization', jwt) // header
.state('token', jwt, config.auth.cookie_options); // cookie
}

_onLoginFailure(result) {
logger.warn(`Failed attempt to login. Full request: ${JSON.stringify(this._request)}`);
logger.warn(`Failed attempt to login. Request payload: ${JSON.stringify(this._request.payload)}`);

switch (result) {
case LoginResults.WRONG_AUTH:
Expand Down Expand Up @@ -134,7 +133,7 @@ class LogoutHandler {
}

_successfulResponse() {
return this._h
return this._h.response()
.code(204)
.state('token', 'expired', config.auth.cookie_options);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import CafeteriaRemoteDataSource from '../../domain/repositories/CafeteriaRemoteDataSource';
import CafeteriaDataSource from '../../domain/repositories/CafeteriaDataSource';
import config from '../../../config';

import fetch from '../../common/utils/fetch';

class CafeteriaRemoteDataSourceImpl extends CafeteriaRemoteDataSource {
class CafeteriaRemoteDataSource extends CafeteriaDataSource {
async fetchRawMenus(url, date) {
return await fetch.getJson(config.menu.url, {stdDate: date});
}
}

export default CafeteriaRemoteDataSourceImpl;
export default CafeteriaRemoteDataSource;
36 changes: 23 additions & 13 deletions lib/interfaces/storage/CafeteriaRepositoryImpl.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -144,30 +144,40 @@ class CafeteriaRepositoryImpl extends CafeteriaRepository {
return [];
}

await this._fetchAndStoreIfNeeded(date);

if (!this._hasMenus(date)) {
logger.warn('No menu after fetch!');
return [];
}

return this.menuCache.menus[date];
}

async _fetchAndStoreIfNeeded(date) {
const nowMillis = Date.now();

const diff = nowMillis - this.menuCache.lastUpdatedMillis;
const cacheOld = diff > config.menu.fetchInterval;
const noData = this.menuCache.menus[date] == null;

if (cacheOld || noData) {
try {
const json = await this.remoteDataSource.fetchRawMenus(config.menu.url, date);
this.menuCache.menus[date] = this.menuConverter.convert(json);
this.menuCache.lastUpdatedMillis = Date.now();
} catch (e) {
logger.error(e);
}
await this._fetchAndStore(date);
}
}

const hasData = Array.isArray(this.menuCache.menus[date]) && this.menuCache.menus[date].length;

if (!hasData) {
logger.warn('No menu after fetch!');
return [];
async _fetchAndStore(date) {
try {
const json = await this.remoteDataSource.fetchRawMenus(config.menu.url, date);
this.menuCache.menus[date] = this.menuConverter.convert(json);
this.menuCache.lastUpdatedMillis = Date.now();
} catch (e) {
logger.error(e);
}
}

return this.menuCache.menus[date];
_hasMenus(date) {
return Array.isArray(this.menuCache.menus[date]) && this.menuCache.menus[date].length;
}
}

Expand Down
38 changes: 38 additions & 0 deletions lib/interfaces/storage/UserLocalDataSource.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This file is part of INU Cafeteria.
*
* Copyright (C) 2020 INU Global App Center <[email protected]>
*
* INU Cafeteria is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* INU Cafeteria is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import UserDataSource from '../../domain/repositories/UserDataSource';
import getEnv from '../../common/utils/env';
import RemoteLoginResult from '../../domain/constants/RemoteLoginResult';

class UserLocalDataSource extends UserDataSource {
userExists(id) {
return String(id) === getEnv('TEST_ID');
}

async fetchLoginResult(id, password) {
if (String(id) === getEnv('TEST_ID') && password === getEnv('TEST_PW')) {
return RemoteLoginResult.SUCCESS;
} else {
return RemoteLoginResult.FAIL;
}
}
}

export default UserLocalDataSource;
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import UserRemoteDataSource from '../../domain/repositories/UserRemoteDataSource';
import config from '../../../config';
import fetch from '../../common/utils/fetch';
import encrypt from '../../common/utils/encrypt';
import logger from '../../common/utils/logger';
import RemoteLoginResult from '../../domain/constants/RemoteLoginResult';
import UserDataSource from '../../domain/repositories/UserDataSource';
import getEnv from '../../common/utils/env';

class UserRemoteDataSource extends UserDataSource {
async userExists(id) {
return id !== getEnv('TEST_ID');
}

class UserRemoteDataSourceImpl extends UserRemoteDataSource {
async fetchLoginResult(id, password) {
try {
return await fetch.postAndGetReponseText(
Expand All @@ -42,4 +47,4 @@ class UserRemoteDataSourceImpl extends UserRemoteDataSource {
}
}

export default UserRemoteDataSourceImpl;
export default UserRemoteDataSource;
12 changes: 8 additions & 4 deletions lib/interfaces/storage/UserRepositoryImpl.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,25 @@ const {Sequelize} = seq;
* Implementation of UserRepository.
*/
class UserRepositoryImpl extends UserRepository {
constructor({db, remoteDataSource}) {
constructor({db, localDataSource, remoteDataSource}) {
super();

this.db = db;
this.userModel = this.db.model('user');

this.remoteDataSource = remoteDataSource;
this.userDataSources = [localDataSource, remoteDataSource];
}

async getRemoteLoginResult(id, password) {
async getLoginResult(id, password) {
if (!id || !password) {
return RemoteLoginResult.FUCK;
}

return this.remoteDataSource.fetchLoginResult(id, password);
for (const dataSource of this.userDataSources) {
if (dataSource.userExists(id)) {
return dataSource.fetchLoginResult(id, password);
}
}
}

async findUserById(id) {
Expand Down
2 changes: 1 addition & 1 deletion test/mocks/UserRepositoryMock.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class UserRepositoryMock extends UserRepository {
super();
}

getRemoteLoginResult(id, password) {
getLoginResult(id, password) {
throw new Error('Not mocked! You need extra mock here');
}

Expand Down
2 changes: 1 addition & 1 deletion test/unit/domain/services/UserService.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('# Logout', () => {
const setRemoteLoginResultMock = function(result) {
const mock = jest.fn(() => result);

resolve(UserService).userRepository.getRemoteLoginResult = mock;
resolve(UserService).userRepository.getLoginResult = mock;

return mock;
};
Expand Down
4 changes: 2 additions & 2 deletions test/unit/interfaces/storage/CafeteriaRepositoryImpl.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import CafeteriaRepositoryImpl from '../../../../lib/interfaces/storage/Cafeteri
import MenuConverter from '../../../../lib/interfaces/converters/MenuConverter';
import config from '../../../../config';
import sequelize from '../../infrastructure/database/sequelizeMock';
import CafeteriaRemoteDataSource from '../../../../lib/domain/repositories/CafeteriaRemoteDataSource';
import CafeteriaDataSource from '../../../../lib/domain/repositories/CafeteriaDataSource';

describe('# getAllCafeteria', () => {
it('should succeed', async () => {
Expand Down Expand Up @@ -140,7 +140,7 @@ describe('# getMenusByCornerId', () => {
const getRepository = function() {
return new CafeteriaRepositoryImpl({
db: sequelize,
remoteDataSource: new (class CafeteriaRemoteDataSourceMock extends CafeteriaRemoteDataSource {
remoteDataSource: new (class CafeteriaRemoteDataSourceMock extends CafeteriaDataSource {
fetchRawMenus() {
return rawMenuExample;
}
Expand Down
Loading

0 comments on commit 850b9fc

Please sign in to comment.