'use strict' /** * Copyright (c) 2017~2022, OBCon Inc. * All rights reserved. */ /** * @file * @copyright 2017~2022, OBCon Inc. * @author gye hyun james kim [pnuskgh@gmail.com] */ //--- http://docs.sequelizejs.com/ const moment = require('moment'); const Sequelize = require('sequelize'); const Model = utils.getClass('include', 'model.js'); class UsersModel extends Model { constructor() { super(); this._title = '사용자'; this._database = db.db_scada; this._tableName = 'users'; } get fieldDesc() { let fieldDescribes = Object.assign({ site: { type: 'integer', len: 11, allowNull: false, defaultValue: 1, validate: {}, title: '사이트', strType: 'integer' }, authenticateId: { type: 'string', len: 64, allowNull: false, validate: {}, title: '아이디', strType: 'string' }, hash: { type: 'string', len: 64, allowNull: false, validate: {}, title: '비밀번호', strType: 'string' }, passwordUpdatedAt: { type: 'date', //--- moment()로 값 지정 allowNull: false, defaultValue: Sequelize.DataTypes.NOW, validate: {}, title: '비밀번호 변경일자', strType: 'date' }, isAdmin: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '관리자 여부', enum: [ [true, '관리자'], [false, '일반사용자'] ], strType: 'boolean' }, isGlobalAdmin: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '글로벌 관리자 여부', strType: 'boolean' }, department: { type: 'string', len: 64, allowNull: true, validate: {}, title: '부서', strType: 'string' }, title: { type: 'string', len: 32, allowNull: true, validate: {}, title: '직책', strType: 'string' }, emailWork: { type: 'string', len: 64, allowNull: true, validate: {}, title: '회사 이메일', strType: 'string' }, emailHome: { type: 'string', len: 64, allowNull: true, validate: {}, title: '개인 이메일', strType: 'string' }, phoneMobile: { type: 'string', len: 32, allowNull: true, validate: {}, title: '핸드폰', strType: 'string' }, phoneWork: { type: 'string', len: 32, allowNull: true, validate: {}, title: '회사 전화', strType: 'string' }, phoneFax: { type: 'string', len: 32, allowNull: true, validate: {}, title: '팩스', strType: 'string' }, postalCode: { type: 'string', len: 8, allowNull: true, defaultValue: '', validate: {}, title: '우편번호', strType: 'string' }, address: { type: 'string', len: 128, allowNull: true, defaultValue: '', validate: {}, title: '주소', strType: 'string' }, addressDetail: { type: 'string', len: 128, allowNull: true, defaultValue: '', validate: {}, title: '상세 주소', strType: 'string' }, isGroup: { //--- 현재 사용하지 않음 type: 'boolean', allowNull: true, defaultValue: false, validate: {}, title: '그룹 여부', strType: 'boolean' }, status: { type: 'string', len: 8, allowNull: false, defaultValue: 'Active', validate: {}, title: '상태', strType: 'select', enum: [ ['Active', 'Active'], ['Inactive', 'Inactive'] ] //--- [value, title]의 배열 }, reportsTo: { //--- 현재 사용하지 않음 type: 'integer', len: 11, allowNull: true, defaultValue: -1, validate: {}, title: '상급자', strType: 'integer' }, originTo: { //--- 원본 user ID type: 'integer', len: 11, allowNull: true, defaultValue: -1, validate: {}, title: '원본 사용자', strType: 'integer' }, //--- To-Do : 향후 Role과 Group 모듈을 추가하여 권한 관리를 한다. roles: { //--- Group과 Role을 추가하여 권한 관리를 하기 전에 임시로 사용 한다. type: 'string', len: 32, allowNull: true, //--- 1 자리 : 정류기 관리자 (0. 사용자, 1. 관리자) defaultValue: '', validate: {}, title: '관리자 역할', strType: 'string', }, smsOptOut: { type: 'boolean', allowNull: false, defaultValue: true, validate: {}, title: 'SMS 알림 수신 여부', //--- true. SMS 수신 거부, false. SMS 수신 enum: [ [true, 'SMS 알림 수신 거부'], [false, 'SMS 알림 수신'] ], strType: 'boolean' }, homeExport: { //--- true. 홈 화면에 "Export" 버튼을 표시 한다. type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: 'Home Export 사용', strType: 'boolean', enum: [ ['false', 'Home Export 사용 않음'], ['true', 'Home Export 사용'] ] }, //--- view : 보고서를 웹 화면에서 조회하는 권한 (2020.07.22 권한 관리하는 코드가 없는 것으로 보임) //--- viewdown : 보고서를 웹 화면에서 조회하고 Excel로 다운로드하는 권한 report1: { type: 'string', len: 8, allowNull: false, defaultValue: 'none', validate: {}, title: '보고서 권한', strType: 'select', enum: [ ['none', '없음'], ['view', '전기방식 시설물 점검 보고서 보기'], ['viewdown', '전기방식 시설물 점검 보고서 보기/저장'] ] }, report1Peroid: { //--- 전기방식 시설물 점검 보고서 보기/저장의 최대 기간 (D.일, M. 월, 관리자는 10년치를 볼 수 있음) type: 'string', len: 8, allowNull: false, defaultValue: '5D', validate: {}, title: '보고서 조회 기간', strType: 'select', enum: [ ['5D', '5일'], ['10D', '10일'], ['1M', '1달'] ] }, mapChart: { //--- use. 지도 화면 하단에 챠트를 표시 type: 'string', len: 8, allowNull: false, defaultValue: 'use', validate: {}, title: '지도 대시보드', strType: 'select', enum: [ ['use', '챠트 사용'], ['none', '챠트 사용 않음'] ] }, homeDetail: { //--- use. 홈 화면에서 홈(분할 화면) 사용 가능 type: 'string', len: 8, allowNull: false, defaultValue: 'none', validate: {}, title: '홈(분할 화면)', strType: 'select', enum: [ ['none', '홈(분할 화면) 사용 않음'], ['use', '홈(분할 화면) 사용'] ] }, group: { type: 'integer', len: 11, allowNull: true, defaultValue: -1, validate: {}, title: '그룹', strType: 'integer' }, role: { type: 'integer', len: 11, allowNull: true, defaultValue: -1, validate: {}, title: '역할', strType: 'integer' }, menuMap: { //--- 지도 메뉴 지정 type: 'string', len: 32, allowNull: false, defaultValue: 'devices/dashboardMap', validate: {}, title: '지도 메뉴', strType: 'select', enum: [ ['devices/dashboardMap', '지도 대시보드'], ['devices/dashboardMap2', '전체 지도'] ] }, // allowApi: { // type: 'boolean', // allowNull: false, // defaultValue: false, // validate: { // }, // title: 'Open API 제어', // enum: [ ['none', '사용 불가'], ['user', '조회 권한'], ['admin', '제어 권한'] ], // strType: 'boolean' // }, apiAuthorization: { type: 'string', len: 8, allowNull: false, defaultValue: 'none', validate: {}, title: 'Open API 제어', strType: 'select', enum: [ ['none', '사용 불가'], ['user', '조회 권한'], ['admin', '제어 권한'] ], }, accessKey: { type: 'string', len: 64, allowNull: false, defaultValue: '', validate: {}, title: 'Access Key', strType: 'string' }, accessSecret: { type: 'string', len: 64, allowNull: false, defaultValue: '', validate: {}, title: 'Access Secret', strType: 'string' }, dashboard: { type: 'string', len: 16, allowNull: false, defaultValue: 'dashboard', validate: {}, title: '홈 화면', strType: 'select', enum: [ ['spaList', '사이트 대시보드'], ['spaMap', '지도 대시보드'], , ['dashboard', '기본 대시보드'] ] }, //--- 필드값 확인 emailConfirmDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '이메일 확인 일자', strType: 'date' }, mobileConfirmDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '핸드폰 확인 일자', strType: 'date' }, //--- 수신 거부 emailOptOut: { type: 'boolean', allowNull: false, defaultValue: true, validate: {}, title: '이메일 수신 거부', strType: 'boolean', enum: [ [true, '이메일 수신 거부'], [false, '이메일 수신'] ] }, emailDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '이메일 수신 거부 일자', //--- emailOptOut : true. 수신 거부 일자, false. 수신 허용 일자 strType: 'date' }, smsOptOut2: { type: 'boolean', allowNull: false, defaultValue: true, validate: {}, title: 'SMS 수신 거부', strType: 'boolean', enum: [ [true, 'SMS 수신 거부'], [false, 'SMS 수신'] ] }, smsDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: 'SMS 수신 거부 일자', //--- smsOptOut2 : true. 수신 거부 일자, false. 수신 허용 일자 strType: 'date' }, salesOptOut: { type: 'boolean', allowNull: false, defaultValue: true, validate: {}, title: '광고 수신 거부', strType: 'boolean', enum: [ [true, '광고 수신 거부'], [false, '광고 수신'] ] }, salesDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '광고 수신 거부 일자', //--- salesOptOut : true. 수신 거부 일자, false. 수신 허용 일자 strType: 'date' }, //--- 이용 동의 privacyAgreement: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '개인정보 이용 동의', strType: 'boolean', enum: [ [true, '개인정보 이용 동의'], [false, '개인정보 이용 거부'] ] }, privacyDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '개인정보 이용 동의 일자', //--- privacyAgreement : true. 개인정보 이용 동의 일자, false. 개인정보 이용 거부 일자 strType: 'date' }, termOfUse: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '이용 약관 동의', strType: 'boolean', enum: [ [true, '이용 약관 동의'], [false, '이용 약관 거부'] ] }, termOfUseDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '이용 약관 동의 일자', //--- termOfUse : true. 이용 약관 동의 일자, false. 이용 약관 거부 일자 strType: 'date' }, termOfUse2: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '위치 기반 서비스 이용 약관 동의', strType: 'boolean', enum: [ [true, '위치 기반 서비스 이용 약관 동의'], [false, '위치 기반 서비스 이용 약관 거부'] ] }, termOfUse2Date: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '위치 기반 서비스 이용 약관 동의 일자', //--- termOfUse2 : true. 위치 기반 서비스 이용 약관 동의 일자, false. 위치 기반 서비스 이용 약관 거부 일자 strType: 'date' }, promotion: { type: 'boolean', allowNull: false, defaultValue: false, validate: {}, title: '프로모션 정보 수신 동의', strType: 'boolean', enum: [ [true, '프로모션 정보 수신 동의'], [false, '프로모션 정보 수신 거부'] ] }, promotionDate: { type: 'date', //--- moment()로 값 지정 allowNull: true, defaultValue: null, validate: {}, title: '프로모션 정보 수신 동의 일자', //--- promotion : true. 프로모션 정보 수신 동의 일자, false. 프로모션 정보 수신 거부 일자 strType: 'date' } }, super.fieldDesc); //--- dashboard : 로그인 후 첫 화면 지정 // if ((config.service.name == 'service_scada_caprotec') || (config.service.name == 'service_scada_ursc')) { // fieldDescribes.dashboard = { // type: 'string', len: 8, // allowNull: false, // defaultValue: 'none', // validate: {}, // title: '홈 메뉴', // strType: 'select', // enum: [ ['list', '사이트 대시보드'], ['map', '지도 대시보드'], , ['old', '기본 대시보드'] ] // }; // } return fieldDescribes; } //--- 데이터 초기화 init() { // this.table.drop(); this.table .sync() //--- Table이 없는 경우 생성 .then(function() { //--- Default data 생성 let query = { where: { deleted: false } }; this.table.findAll(query) .then(function(data) { if (data.length == 0) { this.table.bulkCreate([ { name: 'globalAdmin', site: 1, authenticateId: 'globalAdmin@obcon.biz', hash: utils.getHash('demo1234demo1234'), passwordUpdatedAt: moment().format('YYYY-MM-DD HH:mm:ss'), isAdmin: true, isGlobalAdmin: true, status: 'Active', description: '', assignedUserId: 1, createdBy: 1, updatedBy: 1, deleted: false }, { name: 'admin', site: 1, authenticateId: 'admin@obcon.biz', hash: utils.getHash('demo1234demo1234'), passwordUpdatedAt: moment().format('YYYY-MM-DD HH:mm:ss'), isAdmin: true, isGlobalAdmin: false, status: 'Active', description: '', assignedUserId: 1, createdBy: 1, updatedBy: 1, deleted: false }, { name: 'globalAdmin', site: 2, authenticateId: 'globalAdmin@caprotec.co.kr', hash: utils.getHash('demo1234demo1234'), passwordUpdatedAt: moment().format('YYYY-MM-DD HH:mm:ss'), isAdmin: false, isGlobalAdmin: true, status: 'Active', description: '', assignedUserId: 2, createdBy: 2, updatedBy: 2, deleted: false } ]).catch(utils.obj.loggerError); } }.bind(this)); }.bind(this)); } _userToItem(userOrigin, site) { let item = {}; for (const name in this.fieldDesc) { switch(name) { case 'id': break; case 'originTo': item.originTo = userOrigin.id; case 'site': item.site = site; break; default: item[name] = userOrigin[name]; } } return item; } async updateOrigin(record) { try { const query = { where: { id: record, deleted: false } }; const user = await modules.users.model.table.findOne(query); if ((user != null) && (config.service.services.isMultiService) && (config.service.services.isShareUser)) { if (user.originTo != -1) { console.log(user.id, user.department); const userOrigin = await this.findBySiteAndAuthenticateId(user.site, user.authenticateId, true); console.log(userOrigin.id, userOrigin.department); if (userOrigin != null) { const item = this._userToItem(user, userOrigin.site); item.site = user.site; await modules.users.model.table.update(item, { where: { id: user.id, deleted: false }}); item.site = userOrigin.site; item.originTo = -1; const results = await modules.users.model.table.update(item, { where: { id: userOrigin.id, deleted: false }}); } } } } catch(err) { utils.obj.loggerError(err); } } //--- site : -1. 사이트를 지정 하지 않음 //--- select id, name, site, authenticateId, originTo, phoneMobile, emailWork from users order by site asc, authenticateId asc; //--- delete from users where id = 5; async findBySiteAndAuthenticateId(site, authenticateId, wantOrigin=false) { try { //--- 모든 사용자 읽기 const query = { where: { authenticateId: authenticateId, deleted: false } }; const users = await modules.users.model.table.findAll(query); if (users.length == 0) { return null; } if (config.service.services.isMultiService) { const usersBySite = users.filter(user => user.site == site); if (config.service.services.isShareUser) { const usersByOriginTo = users.filter(user => user.originTo == -1); if (usersByOriginTo.length == 0) { logger.error('Origin user is not exist.') return null; } const userOrigin = usersByOriginTo[0]; const item = this._userToItem(userOrigin, site); if (usersBySite.length == 0) { //--- 사용자 생성 const user = await modules.users.model.table.create(item); return (wantOrigin) ? userOrigin:(user || null); } else { if (usersBySite[0].originTo == -1) { return usersBySite[0]; } else { const results = await modules.users.model.table.update(item, { where: { id: usersBySite[0].id, deleted: false }}); query.where.site = site; const user = await modules.users.model.table.findOne(query); return (wantOrigin) ? userOrigin:user; } } } else { return (0 < usersBySite.length) ? usersBySite[0]:null; } } else { return users[0]; } } catch(err) { utils.obj.loggerError(err); } return null; } async isFindBySiteAndAuthenticateId(site, authenticateId) { try { //--- 모든 사용자 읽기 const users = await modules.users.model.table.findAll({ where: { authenticateId: authenticateId, deleted: false } }); // if (users.length == 0) { // return false; // } // if ((config.service.services.isMultiService) && (config.service.services.isShareUser == false)) { // const usersBySite = users.filter(user => user.site == site); // return (0 < usersBySite.length); // } if (config.service.services.isMultiService) { if (config.service.services.isShareUser) { return (0 < users.length); } else { const usersBySite = users.filter(user => user.site == site); return (0 < usersBySite.length); } } else { const usersBySite = users.filter(user => user.site == site); return (0 < usersBySite.length); } } catch(err) { utils.obj.loggerError(err); } return true; } } module.exports = UsersModel;