obcon-scada / app /include /Authorization.js
chanmin0723's picture
Initial obcon SCADA deploy
e4bf523
Raw
History Blame Contribute Delete
23.7 kB
'use strict'
/**
* Copyright (c) 2017~2020, OBCon Inc.
* All rights reserved.
*/
/**
* @file
* @copyright 2017~2020, OBCon Inc.
* @author gye hyun james kim [pnuskgh@gmail.com]
*/
const fs = require('fs');
const path = require('path');
const moment = require('moment');
//--- 시나리오
//--- 로그인이 완료되면, 사용자의 authorization을 설정하여 세션에 저장 한다.
//--- 일정 주기마다
//--- 권한 확인이 필요한 경우, 세션에 저장된 authorization을 사용하여 권한 확인을 한다.
class Authorization {
constructor() {
this._folder = utils.getPath('files', 'settings', config.service.name, 'roles');
this._filePrefix = 'authorization_'; //--- ${this._filePrefix}${roleId}.json
this._authorization = null; //--- 권한
this._duration = 30 * 60; //--- 세션에서 authorization 갱신 주기 (30분)
this._init();
}
get authorization() {
return this._authorization;
}
set authorization(newValue) {
this._authorization = newValue;
}
_init() {
let paths = [
utils.getPath('files'),
utils.getPath('files', 'settings'),
utils.getPath('files', 'settings', config.service.name),
utils.getPath('files', 'settings', config.service.name, 'roles')
];
for (let idx = 0; idx < paths.length; idx++) {
let path = paths[idx];
if (fs.existsSync(path) == false) {
fs.mkdirSync(path);
}
};
}
//--- Default Authorization을 반환 한다.
//--- 개별 장비별 설정은 포함하지 않는다.
_getDefaultAuthorization(req) {
let version = '0.01'; //--- 디폴트 설정
let versionDate = '2020-08-19'; //--- 디폴트 설정
let showHide = 'show'; //--- 디폴트 설정
let authorization = {
version: version, //--- Authorization 설정의 버전
versionDate: versionDate, //--- Authorization 설정의 버전 시작일
createDate : moment(), //--- Authorization 생성 일시
modules: { //--- Reserved, 모듈에 대한 일반적인 권한 설정
devices: this._getDefaultModuleAuthorization()
}
};
//--- 모듈별 개별 설정
authorization.devices = { //--- 장비 모듈. ${modules}
showHide: showHide, //--- 보여 주기 전체 설정 : show (Default). 모든 장비를 보여 준다. hide. 모든 장비를 보여주지 않는다.
types: { //--- 장비 타입별 담당자 설정
// ${type_1}: {
// title: '정류기', //--- modules.devices.setting.getSettings().types 참조
// use: false, //--- modules.devices.setting.getSettings().types 참조 후 site별 settings 값 반영
// //--- none(Default). 설정 없음, show. 모두 보이기, hide. 모두 감추기
// //--- none인 경우, showHide 설정을 따른다.
// showHide: 'none'
// }
},
show: [], //--- 화면에 표시할 장비 ID 목록
hide: [] //--- 화면에 표시하지 않을 장비 ID 목록
};
//--- modules.devices.setting.getSettings().types을 반영 한다.
let deviceSettings = modules.devices.setting.getSettings();
for (let idx = 0; idx < deviceSettings.types.length; idx++) {
let type = deviceSettings.types[idx];
let roleType = {};
roleType.title = type.title;
roleType.use = type.use;
roleType.showHide = 'none';
authorization.devices.types[`type_${type.name}`] = roleType;
}
//--- site의 디바이스 설정을 읽어서 반영한다.
let types = settingSync.getSetting(req.session.site.siteKey, 'devices', 'types', []);
for (let idx = 0; idx < types.length; idx++) {
let type = types[idx];
authorization.devices.types[`type_${type.name}`].use = type.use;
}
//--- types별 값을 지정하는 로직을 추가할 것
return authorization;
}
resetAuthorization(req, callback) {
let diff = moment().diff(req.session.authorization.createDate) / 1000 / 60; //--- 분
if (this._duration < diff) {
let query = { where: { site: req.session.site.id, id: req.session.user.id, deleted: false } };
modules.users.model.table.findOne(query)
.then(function(user) {
req.session.user = user;
this.setAuthorization(req, user, function(auth) {
req.session.authorization = auth;
callback();
}.bind(this));
}.bind(this)).catch(function(err) {
callback();
});
} else {
callback();
}
}
//--- 특정 사용자의 권한 정보를 확인 한다.
setAuthorization(req, user=null, callback=null) {
logger.info('Start setAuthorization');
let params = { roles: [], authorizations: [], authorization: null };
if (user == null) {
user = req.session.user; //--- 로그인한 사용자의 권한 정보를 확인 한다.
}
logger.info(`${user.name} user : role - ${user.role}, group - ${user.group}`);
//--- 1. 역할(roles) 목록을 가져온다.
let myPromise = new Promise(function(resolve, reject) {
//--- 1-1. 사용자의 role을 가져 온다.
if (user.role == -1) {
resolve();
} else {
let query = { where: { site: user.site, id: user.role, deleted: false } };
modules.roles.model.table.findOne(query)
.then(function(role) {
if (role != null) {
params.roles.push(role);
}
resolve();
}.bind(this)).catch(reject);
}
}.bind(this));
myPromise = myPromise.then(function() {
return new Promise(function(resolve, reject) {
//--- 1-2. 사용자가 속한 그룹의 role을 가져 온다.
if (user.group == -1) {
resolve();
} else {
let query = { where: { site: user.site, id: user.group, deleted: false } };
modules.groups.model.table.findOne(query)
.then(function(group) {
if (group == null) {
resolve();
} else {
if (group.role == -1) {
resolve();
} else {
query = { where: { site: user.site, id: group.role, deleted: false } };
modules.roles.model.table.findOne(query)
.then(function(role) {
if (role != null) {
params.roles.push(role);
}
resolve();
}.bind(this)).catch(reject);
}
}
}.bind(this)).catch(reject);
}
}.bind(this));
}.bind(this));
myPromise = myPromise.then(function() {
return new Promise(function(resolve, reject) {
//--- 4. 장비 정보를 읽어 권한을 최종 확정 한다.
let query = { where: { site: user.site, deleted: false } };
modules.devices.model.table.findAll(query)
.then(function(devices) {
// logger.info('ppp devices count ' + devices.length);
//--- 2. 역할별로 권한을 가져 온다.
for (let idx = 0; idx < params.roles.length; idx++) {
let auth = this.readAuthorization(req, params.roles[idx]);
params.authorizations.push(this.updateDevices(devices, auth));
}
//--- 3. 권한을 조합하여 하나의 권한을 생성 한다.
params.authorization = this._mergeAuthorizations(req, params.authorizations);
this._authorization = params.authorization;
if (callback !== null) {
callback(this._authorization);
}
}.bind(this)).catch(reject);
}.bind(this));
}.bind(this));
myPromise = myPromise.catch(function(err) { //--- reject() 함수에서 에러 처리를 위해 호출 한다.
//--- 권한을 instance와 session에 저장 한다.
this._authorization = null;
}.bind(this));
}
//--- role에 해당하는 권한 정보를 가져 온다.
readAuthorization(req, role) {
if (role == null) {
return this._getDefaultAuthorization(req);
}
let roleId = role.id;
let filename = `${this._folder}${path.sep}${this._filePrefix}${roleId}.json`;
let authorization = null;
if (fs.existsSync(filename)) {
let buf = fs.readFileSync(filename, { encoding: 'utf8' });
authorization = this._mergeAuthorizations(req, [ JSON.parse(buf) ]);
} else {
authorization = this._getDefaultAuthorization(req);
}
return authorization;
}
//--- Reserved, 모듈의 디폴트 권한 설정 반환
_getDefaultModuleAuthorization() {
return {
access: 'Not Set', //--- 접속 권한 : Enable, Not Set (Default), Disabled
list: 'Not Set', //--- 목록 조회 권한 : All, Group, Owner, Not Set (Default), None
view: 'Not Set', //--- 조회 권한 : All, Group, Owner, Not Set (Default), None
edit: 'Not Set', //--- 등록/수정 권한 : All, Group, Owner, Not Set (Default), None
delete: 'Not Set', //--- 삭제 권한 : All, Group, Owner, Not Set (Default), None
import: 'Not Set', //--- 목록 조회 권한 : All, Not Set (Default), None
export: 'Not Set' //--- 목록 조회 권한 : All, Group, Owner, Not Set (Default), None
};
}
//--- Reserved, 모듈의 디폴트 권한 설정 2개를 병합하여 반환 한다.
_mergeDefaultModuleAuthorization(auth1, auth2) {
let auth = {};
let data = [ 'access', 'list', 'view', 'edit', 'delete', 'import', 'export' ];
for (let idx = 0; idx < data.length; idx++) {
let item = data[idx];
let access1 = auth1[item];
let access2 = auth2[item];
let access = 'Not Set';
switch(item) {
case 'access':
if (access1 == 'Enable') {
access = 'Enable';
} else if (access1 = 'Not Set') {
access = access2;
} else { //--- access1 = 'Disabled'
if (access2 == 'Enable') {
access = 'Enable';
} else if (access2 = 'Not Set') {
access = access1;
} else { //--- access2 = 'Disabled'
access = 'Disabled';
}
}
break;
case 'import':
if (access1 == 'Enable') {
access = 'Enable';
} else if (access1 = 'Not Set') {
access = access2;
} else { //--- access1 = 'None'
if (access2 == 'Enable') {
access = 'Enable';
} else if (access2 = 'Not Set') {
access = access1;
} else { //--- access2 = 'None'
access = 'None';
}
}
break;
case 'list':
case 'view':
case 'edit':
case 'delete':
case 'export':
default:
if (access1 == 'All') {
access = 'All';
} else if (access1 = 'Group') {
if (access2 == 'All') {
access = 'All';
} else if (access2 = 'Group') {
access = 'Group';
} else if (access2 = 'Owner') {
access = 'Group';
} else if (access2 = 'Not Set') {
access = access1;
} else { //--- access2 = 'None'
access = 'Group';
}
} else if (access1 = 'Owner') {
if (access2 == 'All') {
access = 'All';
} else if (access2 = 'Group') {
access = 'Group';
} else if (access2 = 'Owner') {
access = 'Owner';
} else if (access2 = 'Not Set') {
access = access1;
} else { //--- access2 = 'None'
access = 'Owner';
}
} else if (access1 = 'Not Set') {
access = access2;
} else { //--- access1 = 'None'
if (access2 == 'All') {
access = 'All';
} else if (access2 = 'Group') {
access = 'Group';
} else if (access2 = 'Owner') {
access = 'Owner';
} else if (access2 = 'Not Set') {
access = access1;
} else { //--- access2 = 'None'
access = 'None';
}
}
break;
}
auth[item] = access;
}
return auth;
}
//--- Authorizations을 하나로 병합 한다.
//--- 값이 없는 경우에는 디폴트 값으로 채운다.
_mergeAuthorizations(req, authorizations) {
if (authorizations.length == 0) {
return this._getDefaultAuthorization(req);
}
let rtAuthorization = authorizations[0];
for (let idx = 1; idx < authorizations.length; idx++) {
let authorization = authorizations[idx];
rtAuthorization.version = (rtAuthorization.version < authorization.version) ? authorization.version: rtAuthorization.version;
rtAuthorization.versionDate = (rtAuthorization.versionDate < authorization.versionDate) ? authorization.versionDate: rtAuthorization.versionDate;
rtAuthorization.modules.devices = this._mergeDefaultModuleAuthorization(rtAuthorization.modules.devices, authorization.modules.devices);
if ((rtAuthorization.devices.showHide == 'show') || (authorization.devices.showHide == 'show')) {
rtAuthorization.devices.showHide = 'show';
} else {
rtAuthorization.devices.showHide = 'hide';
}
let deviceSettings = modules.devices.setting.getSettings();
for (let idx = 0; idx < deviceSettings.types.length; idx++) {
let type = deviceSettings.types[idx];
let name = `type_${type.name}`;
let roleType = {};
roleType.title = type.title;
roleType.use = ((rtAuthorization.devices.types[name].use) || ((authorization.devices.types[name].use)));
if (rtAuthorization.devices.types[name].showHide == 'none') {
roleType.showHide = authorization.devices.types[name].showHide;
} else if (rtAuthorization.devices.types[name].showHide == 'show') {
roleType.showHide = 'show';
} else { //--- rtAuthorization.devices.types[name].showHide == 'hide'
if (authorization.devices.types[name].showHide == 'none') {
roleType.showHide = 'hide';
} else if (authorization.devices.types[name].showHide == 'show') {
roleType.showHide = 'show';
} else { //--- authorization.devices.types[name].showHide == 'hide'
roleType.showHide = 'hide';
}
}
rtAuthorization.devices.types[name] = roleType;
}
//--- site의 디바이스 설정을 읽어서 반영한다.
let types = settingSync.getSetting(req.session.site.siteKey, 'devices', 'types', []);
for (let idx = 0; idx < types.length; idx++) {
let type = types[idx];
rtAuthorization.devices.types[`type_${type.name}`].use = type.use;
}
for (let idx = 0; idx < authorization.devices.show.length; idx++) {
let deviceId = authorization.devices.show[idx];
if (rtAuthorization.devices.show.includes(deviceId) == false) {
rtAuthorization.devices.show.push(deviceId);
}
}
for (let idx = 0; idx < authorization.devices.hide.length; idx++) {
let deviceId = authorization.devices.hide[idx];
if (rtAuthorization.devices.hide.includes(deviceId) == false) {
rtAuthorization.devices.hide.push(deviceId);
}
}
}
let hides = [];
for (let idx = 0; idx < rtAuthorization.devices.hide.length; idx++) {
let deviceId = rtAuthorization.devices.hide[idx];
if (rtAuthorization.devices.show.includes(deviceId) == false) {
hides.push(deviceId);
}
}
rtAuthorization.createDate = moment();
return rtAuthorization;
}
//--- 전체 장비 목록을 받아 권한 설정을 최신화 한다.
updateDevices(devices, authorization=null) {
let flagUpdate = false;
if (authorization == null) {
authorization = this._authorization;
flagUpdate = true;
}
if (authorization == null) {
console.log('pppppppppp updateDevices');
}
let show = [];
let hide = [];
for (let idx = 0; idx < devices.length; idx++) {
let device = devices[idx];
let authType = authorization.devices.types[`type_${device.type}`];
if (authType == 'show') {
show.push(device.id);
} else if (authType == 'hide') {
hide.push(device.id);
} else {
if (authorization.devices.showHide == 'show') {
if (authorization.devices.hide.includes(device.id)) {
hide.push(device.id);
} else {
show.push(device.id);
}
} else {
if (authorization.devices.show.includes(device.id)) {
show.push(device.id);
} else {
hide.push(device.id);
}
}
}
}
authorization.devices.show = show;
authorization.devices.hide = hide;
if (flagUpdate) {
this._authorization = authorization;
}
return authorization;
}
//--- 하나의 role에 해당하는 권한 파일을 생성 한다.
writeAuthorization(roleId, authorization) {
let filename = `${this._folder}${path.sep}${this._filePrefix}${roleId}.json`;
fs.writeFileSync(filename, JSON.stringify(authorization), { encoding: 'utf8' });
}
//--- 전체 장비 목록을 받아 조회 권한이 있는 장비 목록만 반환 한다.
getAuthorizedDevices(devices) {
let rtDevices = [];
let auth = this.updateDevices(devices);
let show = auth.devices.show;
for (let idx = 0; idx < devices.length; idx++) {
let device = devices[idx];
if (show.includes(device.id)) {
rtDevices.push(device);
}
}
return rtDevices;
}
//--- 전체 알람 목록을 받아 조회 권한이 있는 알람 목록만 반환 한다.
getAuthorizedNotifications(notifications) {
let rtNotifications = [];
let show = this._authorization.devices.show;
for (let idx = 0; idx < notifications.length; idx++) {
let notification = notifications[idx];
if (show.includes(notification.device)) {
rtNotifications.push(notification);
}
}
return rtNotifications;
}
//--- 역할 등록/수정 화면에서 전달된 데이터를 반영 한다.
updateUserRole(role) {
let deviceSettings = modules.devices.setting.getSettings();
for (let idx = 0; idx < deviceSettings.types.length; idx++) {
let typeName = `type_${deviceSettings.types[idx].name}`;
this._authorization.devices.types[typeName].showHide = role.types[typeName];
}
this._authorization.devices.show = role.show;
this._authorization.devices.hide = role.hide;
// let newHide = [];
// let hide = this._authorization.devices.hide;
// for (let idx = 0; idx < hide.length; idx++) {
// let deviceId = hide[idx];
// if (role.show.includes(deviceId) == false) {
// newHide.push(deviceId);
// }
// }
// this._authorization.devices.hide = newHide;
}
}
module.exports = Authorization;