Spaces:
Sleeping
Sleeping
| /** | |
| * 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; | |