k2hr3-app
Version:
K2HR3 Web Application is K2hdkc based Resource and Roles and policy Rules
1,539 lines (1,375 loc) • 48.1 kB
JSX
/*
*
* K2HR3 Web Application
*
* Copyright 2017 Yahoo Japan Corporation.
*
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
* common management information for the cloud.
* K2HR3 can dynamically manage information as "who", "what", "operate".
* These are stored as roles, resources, policies in K2hdkc, and the
* client system can dynamically read and modify these information.
*
* For the full copyright and license information, please view
* the license file that was distributed with this source code.
*
* AUTHOR: Takeshi Nakatani
* CREATE: Tue Aug 15 2017
* REVISION:
*
*/
import React from 'react';
import ReactDOM from 'react-dom'; // eslint-disable-line no-unused-vars
import PropTypes from 'prop-types';
import Paper from '@mui/material/Paper'; // For contents wrap
import Box from '@mui/material/Box';
// Styles
import { r3Container } from './r3styles'; // But nothing for r3Container now.
// Parts
import R3AppBar from './r3appbar'; // AppBar
import R3MainTree from './r3maintree'; // Main TreeView
import R3Toolbar from './r3toolbar'; // Toolbar
import R3MsgBox from './r3msgbox'; // Message Box
import R3AboutDialog from './r3aboutdialog'; // About Dialog
import R3AccountDialog from './r3accountdialog'; // Account Dialog
import R3SigninDialog from './r3signincreddialog'; // SignIn by Credential Dialog
import R3Progress from './r3progress'; // Progress
// For contents
import R3Resource from './r3resource';
import R3Role from './r3role';
import R3Policy from './r3policy';
import R3Service from './r3service';
// For context
import { R3CommonContext } from './r3commoncontext';
// Utilities
import R3Provider from '../util/r3provider';
import R3Message from '../util/r3message';
import { localTenantPrefix } from '../util/r3define';
import { clientTypes } from '../util/r3device';
import { r3LicensesJsonString } from '../util/r3licenses';
import { r3VersionString } from '../util/r3version';
import { resourceType, roleType, policyType, serviceType, errorType, warningType, infoType, signinUnknownType, signinUnscopedToken, signinCredential } from '../util/r3types'; // eslint-disable-line no-unused-vars
import { r3DeepCompare, r3IsEmptyStringObject, r3CompareString, r3CompareCaseString, r3IsEmptyString, r3IsEmptyEntity, r3IsEmptyEntityObject, r3ConvertFromJSON, r3IsSafeTypedEntity, r3DeepClone } from '../util/r3util';
//
// Container Class
//
export default class R3Container extends React.Component
{
static propTypes = {
title: PropTypes.string
};
static defaultProps = {
title: 'K2HR3'
};
// State for not render
r3provider = new R3Provider(this.cbProgressControl); // [NOTE] signin must not be specified here.
contentUpdating = false;
progressDisplayFunc = null; // Callback from R3Progress for registering its method function.
// Licenses
licensesObj = r3ConvertFromJSON(r3LicensesJsonString);
// for dispatching contents
static dispUnique = 0;
// State
//
// [NOTE] type/service in selected
//
// If selected.type is ROLE or POLICY or RESOURCE and selected.service
// is empty, it means that "ROLE/POLICY/RESOURCE" top or the pass under
// those is selected.
// If selected.type is SERVICE, it means SERVICE top or "service name"
// under SERVICE top is selected.
// On this case, selected.service is set empty or "service name".
// If selected.service is empty, it means that SERVICE top is selected.
// If selected.service is not empty, "service name" under SERVICE top is
// selected.
// If selected.service is not empty and selected.type is ROLE or POLICY
// or RESOURCE, it means that ROLE/POLICY/RESOURCE under "service name"
// (under SERVICE) is selected.
// At this case, when selected.path is not empty,
// "SERVICE > service name > ROLE/POLICY/RESOURCE > path" is selected.
//
// <<DETAIL EXAMPLE>>
// [type] [service] [path] [selected item]
// ROLE/POLICY/RESOURCE empty empty/path ROLE/POLICY/RESOURCE top or path under it
// SERVICE empty empty SERVICE top
// SERVICE service name empty "SERVICE > service name"
// ROLE/POLICY/RESOURCE service name empty "SERVICE > service name > ROLE/POLICY/RESOURCE"
// ROLE/POLICY/RESOURCE service name path "SERVICE > service name > ROLE/POLICY/RESOURCE > path"
//
state = {
selected: {
tenant: null,
type: null,
service: null,
path: null
},
tenants: [],
mainTree: this.r3provider.getEmptyTreeList(true),
mainTreeEndock: !clientTypes.isMobile,
mainTreeDocked: (clientTypes.isMobile || clientTypes.isTablet ? false : true),
mainTreeOpen: false,
service: {},
role: {},
policy: {},
resource: {},
toolbarData: this.r3provider.getPathDetailInfo(null, null, false, false, null, null),
message: new R3Message(this.r3provider.getR3TextRes().iNotSelectTenant),
aboutDialogOpen: false,
licensePackage: null,
licenseType: null,
licenseText: null,
r3VersionText: null,
accountDialogOpen: false,
username: this.r3provider.getR3Context().getSafeUserName(),
unscopedtoken: this.r3provider.getR3Context().getSafeUnscopedToken(),
useLocalTenant: this.r3provider.getR3Context().useLocalTenant(),
signinDialogOpen: false
};
constructor(props)
{
super(props);
// Binding(do not define handlers as arrow functions for performance)
this.handleIsContentUpdating = this.handleIsContentUpdating.bind(this);
this.handleTenantChange = this.handleTenantChange.bind(this);
this.handleLocalTenantCreate = this.handleLocalTenantCreate.bind(this);
this.handleLocalTenantChange = this.handleLocalTenantChange.bind(this);
this.handleLocalTenantDelete = this.handleLocalTenantDelete.bind(this);
this.handleTypeChange = this.handleTypeChange.bind(this);
this.handleListItemChange = this.handleListItemChange.bind(this);
this.handleNameItemInServiceChange = this.handleNameItemInServiceChange.bind(this);
this.handleTypeInServiceChange = this.handleTypeInServiceChange.bind(this);
this.handleListItemInServiceChange = this.handleListItemInServiceChange.bind(this);
this.handleTreeDetach = this.handleTreeDetach.bind(this);
this.handleTreeOpen = this.handleTreeOpen.bind(this);
this.handleTreePopupClose = this.handleTreePopupClose.bind(this);
this.handleTreeDocking = this.handleTreeDocking.bind(this);
this.handleMoveToUpPath = this.handleMoveToUpPath.bind(this);
this.handleCreatePath = this.handleCreatePath.bind(this);
this.handleCheckConflictPath = this.handleCheckConflictPath.bind(this);
this.handleCheckConflictServiceName = this.handleCheckConflictServiceName.bind(this);
this.handleDeletePath = this.handleDeletePath.bind(this);
this.handleCreateService = this.handleCreateService.bind(this);
this.handleCreateServiceTenant = this.handleCreateServiceTenant.bind(this);
this.handleDeleteService = this.handleDeleteService.bind(this);
this.handleContentUpdating = this.handleContentUpdating.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handleServiceSave = this.handleServiceSave.bind(this);
this.handleSign = this.handleSign.bind(this);
this.handleAbout = this.handleAbout.bind(this);
this.handAboutDialogClose = this.handAboutDialogClose.bind(this);
this.handleAccount = this.handleAccount.bind(this);
this.handAccountDialogClose = this.handAccountDialogClose.bind(this);
this.handSignInDialogClose = this.handSignInDialogClose.bind(this);
this.cbProgressControl = this.cbProgressControl.bind(this); // For progress callback from provider
this.cbRefRegister = this.cbRefRegister.bind(this); // For registering callback from progress
// styles
this.sxClasses = r3Container(props.theme);
}
componentDidMount()
{
// Initialize tenant
this.r3provider.getTenantList(false, this.state.useLocalTenant, (error, resobj) => this.cbTenantList(error, resobj));
}
//
// Re-Initialize by sign in/out
//
componentReinitialize(isSignIn, username, unscopedtoken)
{
// Re-Initialize provider object
this.r3provider = new R3Provider(this.cbProgressControl, isSignIn, username, unscopedtoken);
// Re-Initialize & Update state
this.updateState({
selected: {
tenant: null,
type: null,
service: null,
path: null
},
tenants: [],
mainTree: this.r3provider.getEmptyTreeList(true),
mainTreeEndock: !clientTypes.isMobile,
mainTreeDocked: (clientTypes.isMobile || clientTypes.isTablet ? false : true),
mainTreeOpen: false,
service: {},
role: {},
policy: {},
resource: {},
toolbarData: this.r3provider.getPathDetailInfo(null, null, false, false, null, null),
aboutDialogOpen: false,
licensePackage: null,
licenseType: null,
licenseText: null,
r3VersionText: null,
accountDialogOpen: false,
username: username,
unscopedtoken: unscopedtoken,
signinDialogOpen: false
});
if(isSignIn){
// Re-Initialize tenant list
this.r3provider.getTenantList(true, this.state.useLocalTenant, (error, resobj) => this.cbTenantList(error, resobj));
// All parts updates
this.updateStateAllParts(this.state.selected.tenant, this.state.selected.service, this.state.selected.type, this.state.selected.path, false, (isSignIn ? (this.r3provider.getR3TextRes().iSignined + this.r3provider.getR3TextRes().iNotSignin) : (this.r3provider.getR3TextRes().iSignouted + this.r3provider.getR3TextRes().iNotSignin)));
}
}
//
// Utility for updating State
//
updateState(newState, message = null, type = infoType)
{
if(r3IsEmptyEntity(newState)){
newState = {};
}
if(!this.r3provider.getR3Context().isLogin()){
var r3providerMsg = this.r3provider.getR3Context().getErrorMsg();
if(!r3IsEmptyString(r3providerMsg)){
newState.message = new R3Message(r3providerMsg, errorType);
}else{
newState.message = new R3Message(this.r3provider.getR3TextRes().iNotSignin);
}
}else if(r3IsEmptyString(message)){
if(undefined === newState.selected){
if(undefined === this.state.selected || r3IsEmptyStringObject(this.state.selected.tenant, 'name')){
newState.message = new R3Message(this.r3provider.getR3TextRes().iNotSelectTenant);
}else if(null === this.state.selected.type || null === this.state.selected.path){
newState.message = new R3Message(this.r3provider.getR3TextRes().iNotSelectPath);
}else{
newState.message = new R3Message();
}
}else if(null === newState.selected.tenant){
newState.message = new R3Message(this.r3provider.getR3TextRes().iNotSelectTenant);
}else if(null === newState.selected.type || null === newState.selected.path){
newState.message = new R3Message(this.r3provider.getR3TextRes().iNotSelectPath);
}else{
newState.message = new R3Message();
}
}else{
newState.message = new R3Message(message, type);
}
this.setState(newState);
}
//
// Callback for provider
//
cbTenantList(error, tenants)
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
}else{
this.updateState({
tenants: tenants
}, ((!r3IsSafeTypedEntity(tenants, 'array') || 0 === tenants.length) ? this.r3provider.getR3TextRes().iNotHaveAnyTenant : null));
}
}
//
// Update MainTree List
//
updateMainTreeList(selectedTenant, selectedService, selectedType, selectedPath, callback)
{
console.info('CALL : updateMainTreeList');
let _callback = callback;
let _tenant = selectedTenant;
let _service = selectedService;
let _type = selectedType;
let _path = selectedPath;
this.cbProgressControl(true); // collectively display progress
this.r3provider.getAllTreeList(_tenant, (error, resobj) =>
{
// always error is null
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
_callback(error, null);
return;
}
// set seleted flag
this.r3provider.selectTreeList(resobj, _service, _type, _path);
this.cbProgressControl(false); // collectively undisplay progress
_callback(null, resobj);
});
}
//
// Update Service Data
//
updateServiceData(selectedTenant, selectedService, treeList, callback)
{
console.info('CALL : updateServiceData');
let _callback = callback;
let _tenant = selectedTenant;
let _service = selectedService;
if( r3IsEmptyStringObject(_tenant, 'name') ||
r3IsEmptyString(_service) )
{
// update state
_callback(null, {});
return;
}
this.cbProgressControl(true); // collectively display progress
// check owner
if(!this.r3provider.checkServiceOwnerInTreeList(treeList, _service)){
this.cbProgressControl(false); // collectively undisplay progress
// tenant is not service owner, then service data is empty
_callback(null, {});
return;
}
this.r3provider.getServiceData(_tenant, _service, (error, resobj) =>
{
this.cbProgressControl(false); // collectively undisplay progress
if(null !== error){
console.info(error.message);
_callback(error, null);
return;
}
if(null === resobj){
console.error('Could not get role data for tenant(' + _tenant + '), service(' + _service + ')');
resobj = {};
}
_callback(null, resobj);
});
}
//
// Update Role Data
//
updateRoleData(selectedTenant, selectedService, selectedType, selectedPath, callback)
{
console.info('CALL : updateRoleData');
let _callback = callback;
let _tenant = selectedTenant;
let _service = selectedService;
let _type = selectedType;
let _path = selectedPath;
if( r3IsEmptyStringObject(_tenant, 'name') ||
!r3CompareString(_type, roleType) ||
r3IsEmptyString(_path) )
{
// update state
_callback(null, {});
return;
}
this.r3provider.getRoleData(_tenant, _service, _path, false, (error, resobj) =>
{
if(null !== error){
console.info(error.message);
_callback(error, null);
return;
}
if(null === resobj){
console.error('Could not get role data for tenant(' + _tenant + '), path(' + _path + ')');
resobj = {};
}
_callback(null, resobj);
});
}
//
// Update Policy Data
//
updatePolicyData(selectedTenant, selectedService, selectedType, selectedPath, callback)
{
console.info('CALL : updatePolicyData');
let _callback = callback;
let _tenant = selectedTenant;
let _service = selectedService;
let _type = selectedType;
let _path = selectedPath;
if( r3IsEmptyStringObject(_tenant, 'name') ||
!r3CompareString(_type, policyType) ||
r3IsEmptyString(_path) )
{
// update state
_callback(null, {});
return;
}
this.r3provider.getPolicyData(_tenant, _service, _path, (error, resobj) =>
{
if(null !== error){
console.info(error.message);
_callback(error, null);
return;
}
if(null === resobj){
console.error('Could not get policy data for tenant(' + _tenant + '), path(' + _path + ')');
resobj = {};
}
_callback(null, resobj);
});
}
//
// Update Resource Data
//
updateResourceData(selectedTenant, selectedService, selectedType, selectedPath, callback)
{
console.info('CALL : updateResourceData');
let _callback = callback;
let _tenant = selectedTenant;
let _service = selectedService;
let _type = selectedType;
let _path = selectedPath;
if( r3IsEmptyStringObject(_tenant, 'name') ||
!r3CompareString(_type, resourceType) ||
r3IsEmptyString(_path) )
{
// update state
_callback(null, {});
return;
}
this.r3provider.getResourceData(_tenant, _service, _path, false, (error, resobj) =>
{
if(null !== error){
console.info(error.message);
_callback(error, null);
return;
}
if(null === resobj){
console.error('Could not get resource data for tenant(' + _tenant + '), path(' + _path + ')');
resobj = {};
}
_callback(null, resobj);
});
}
updateStateAllParts(tenant, service, type, path, openMainTree, message = null, msgType = infoType)
{
// new state data
let newState = {
selected: {
tenant: tenant,
service: service,
type: type,
path: path
},
mainTreeOpen: (this.state.mainTreeDocked ? false : openMainTree),
};
let _tenant = tenant;
let _service = service;
let _type = type;
let _path = path;
let _message = message;
let _msgType = msgType;
this.cbProgressControl(true); // collectively display progress
this.updateMainTreeList(_tenant, _service, _type, _path, (error, mainTree) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
console.info(error.message);
return;
}
newState.mainTree = mainTree;
newState.toolbarData = this.r3provider.getPathDetailInfo(_tenant, _service, this.r3provider.checkServiceOwnerInTreeList(newState.mainTree, _service), this.r3provider.checkServiceTenantInTreeList(newState.mainTree, _service), _type, _path);
this.updateServiceData(_tenant, _service, mainTree, (error, serviceData) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
console.info(error.message);
return;
}
newState.service= serviceData;
this.updateRoleData(_tenant, _service, _type, _path, (error, role) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
console.info(error.message);
this.updateState(null, error.message, errorType);
return;
}
newState.role = role;
this.updatePolicyData(_tenant, _service, _type, _path, (error, policy) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
console.info(error.message);
this.updateState(null, error.message, errorType);
return;
}
newState.policy = policy;
this.updateResourceData(_tenant, _service, _type, _path, (error, resource) =>
{
this.cbProgressControl(false); // collectively undisplay progress
if(null !== error){
console.info(error.message);
this.updateState(null, error.message, errorType);
return;
}
newState.resource = resource;
// update all
this.updateState(newState, _message, _msgType);
});
});
});
});
});
}
//
// Handle Check updating
//
handleIsContentUpdating()
{
return this.contentUpdating;
}
//
// Handle Tenant in MainTree Change
//
handleTenantChange(tenant)
{
let type = (r3DeepCompare(tenant, this.state.selected.tenant) ? this.state.selected.type : null);
let service = (r3DeepCompare(tenant, this.state.selected.tenant) ? this.state.selected.service : null);
let path = (r3DeepCompare(tenant, this.state.selected.tenant) ? this.state.selected.path : null);
this.updateStateAllParts(tenant, service, type, path, false, this.r3provider.getR3TextRes().iSucceedChangeTenant);
}
//
// Update Tenant List Callback for provider
//
// [NOTE]
// This CallBack is for creating/updating a Local Tenant.
//
cbUpdateChangeTenant(error, tenants, tenantname)
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
}else{
// update tenant list
this.updateState({
tenants: r3DeepClone(tenants)
}, ((!r3IsSafeTypedEntity(tenants, 'array') || 0 === tenants.length) ? this.r3provider.getR3TextRes().iNotHaveAnyTenant : null));
// change selected tenant
let _selectedTenant = null;
if(!r3IsEmptyString(tenantname)){
let _tenantName;
if(0 === tenantname.indexOf(localTenantPrefix)){
_tenantName = tenantname;
}else{
_tenantName = localTenantPrefix + tenantname;
}
tenants.map( (item) => {
if(!r3IsEmptyString(item.name) && item.name == _tenantName){
// found
_selectedTenant = r3DeepClone(item);
}
});
}
this.updateStateAllParts(_selectedTenant, null, null, null, false, this.r3provider.getR3TextRes().iSucceedChangeTenant);
}
}
//
// Handle Create Local Tenant in MainTree
//
// name : Local Tenant name(prefix with local@) to create
// display : Display name allowed empty
// description : Description name allowed empty
// users : User name list included self name
//
handleLocalTenantCreate(name, display, description, users)
{
console.info('CALL : handleLocalTenantCreate');
let _name = name;
let _display = display;
let _description= description;
let _users = r3DeepClone(users);
this.cbProgressControl(true); // collectively display progress
this.r3provider.createLocalTenant(_name, _display, _description, _users, (error) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
this.updateState(null, this.r3provider.getR3TextRes().eLocalTenantCreate + error.message, errorType);
return;
}
//
// update tenant list and change to new local tenant
//
this.r3provider.getTenantList(true, this.state.useLocalTenant, (error, resobj) => this.cbUpdateChangeTenant(error, resobj, _name));
this.cbProgressControl(false); // collectively undisplay progress
});
}
//
// Handle Change Local Tenant in MainTree
//
// name : Local Tenant name(prefix with local@) to change
// id : Local Tenant ID
// display : Display name allowed empty
// description : Description name allowed empty
// users : User name list
//
handleLocalTenantChange(name, id, display, description, users)
{
console.info('CALL : handleLocalTenantChange');
let _name = name;
let _id = id;
let _display = display;
let _description= description;
let _users = r3DeepClone(users);
this.cbProgressControl(true); // collectively display progress
this.r3provider.updateLocalTenant(_name, _id, _display, _description, _users, (error) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
this.updateState(null, this.r3provider.getR3TextRes().eLocalTenantUpdate + error.message, errorType);
return;
}
//
// update tenant list and change to new local tenant
//
this.r3provider.getTenantList(true, this.state.useLocalTenant, (error, resobj) => this.cbUpdateChangeTenant(error, resobj, _name));
this.cbProgressControl(false); // collectively undisplay progress
});
}
//
// Handle Delete Local Tenant in MainTree
//
// name : Local Tenant name(prefix with local@) to delete
// id : Local Tenant id
//
handleLocalTenantDelete(name, id)
{
console.info('CALL : handleLocalTenantDelete');
let _name = name;
let _id = id;
this.cbProgressControl(true); // collectively display progress
this.r3provider.deleteLocalTenant(_name, _id, (error) =>
{
if(null !== error){
this.cbProgressControl(false); // collectively undisplay progress
this.updateState(null, this.r3provider.getR3TextRes().eLocalTenantDelete + error.message, errorType);
return;
}
//
// update tenant list and change to new local tenant
//
this.r3provider.getTenantList(true, this.state.useLocalTenant, (error, resobj) => this.cbUpdateChangeTenant(error, resobj, null));
this.cbProgressControl(false); // collectively undisplay progress
});
}
//
// Handle Top level type in MainTree Change
//
handleTypeChange(newType)
{
let type = r3IsEmptyStringObject(this.state.selected.tenant, 'name') ? null : newType;
this.updateStateAllParts(this.state.selected.tenant, null, type, null, true, (null === type ? this.r3provider.getR3TextRes().iNotSelectTenant : this.r3provider.getR3TextRes().iSucceedChangeType));
}
//
// Handle ROLE/POLICY/RESOURCE(not under SERVICE) Item Change
//
handleListItemChange(type, path)
{
// this handler is called when "tenant > ROLE/POLICY/RESOURCE/ > item" is selected.
// it means service name is empty(not selected).
//
this.updateStateAllParts(this.state.selected.tenant, null, type, path, false, this.r3provider.getR3TextRes().iSucceedChangePath);
}
// Handle Service name under "SERVICE" Change
handleNameItemInServiceChange(servicename)
{
//
// Type is serviceType("service")
//
let message = this.r3provider.checkServiceOwnerInTreeList(this.state.mainTree, servicename) ? this.r3provider.getR3TextRes().iSucceedChangeServiceOwner : this.r3provider.getR3TextRes().iSucceedChangeServiceName;
this.updateStateAllParts(this.state.selected.tenant, servicename, serviceType, null, true, message);
}
// Handle Type(ROLE/POLICY/RESOURCE) under "SERVICE > Service name" Change
handleTypeInServiceChange(servicename, type_in_service)
{
this.updateStateAllParts(this.state.selected.tenant, servicename, type_in_service, null, true, this.r3provider.getR3TextRes().iSucceedChangeServiceType);
}
// Handle Item under "SERVICE > Service name > Type(ROLE/POLICY/RESOURCE)" Change
handleListItemInServiceChange(servicename, type_in_service, path)
{
this.updateStateAllParts(this.state.selected.tenant, servicename, type_in_service, path, false, this.r3provider.getR3TextRes().iSucceedChangeServicePath);
}
//
// Handle MainTree open
//
handleTreeOpen()
{
this.updateState({
mainTreeDocked: false,
mainTreeOpen: true
});
}
//
// Handle MainTree popup close
//
handleTreePopupClose()
{
this.updateState({
mainTreeOpen: false
});
}
//
// Handle MainTree docking status
//
handleTreeDetach()
{
this.handleTreeDocking(false);
}
//
// Handle MainTree docking status
//
handleTreeDocking(isDocking)
{
this.updateState({
mainTreeDocked: isDocking,
mainTreeOpen: false
});
}
//
// Handle Move path
//
handleMoveToUpPath()
{
//
// Check for not move up type
//
// no tenant ||
// unknown type ||
// SERVICE top(type & empty service) ||
// ROLE/POLICY/RESOURCE top(type & empty service or path) ||
//
if( r3IsEmptyStringObject(this.state.selected.tenant, 'name') ||
(!r3CompareCaseString(serviceType, this.state.selected.type) && !r3CompareCaseString(roleType, this.state.selected.type) && !r3CompareCaseString(policyType, this.state.selected.type) && !r3CompareCaseString(resourceType, this.state.selected.type)) ||
(r3CompareCaseString(serviceType, this.state.selected.type) && r3IsEmptyString(this.state.selected.service)) ||
((r3CompareCaseString(roleType, this.state.selected.type) || r3CompareCaseString(policyType, this.state.selected.type) || r3CompareCaseString(resourceType, this.state.selected.type)) && (r3IsEmptyString(this.state.selected.service) && r3IsEmptyString(this.state.selected.path))) )
{
console.error('Current path is not existed.');
return;
}
// make new type/service/path
let _newType;
let _newServiceName;
let _newPath;
let _message;
let separatorPos;
if(r3CompareCaseString(serviceType, this.state.selected.type) && !r3IsEmptyString(this.state.selected.service)){
// now "SERVICE > service name", move to SERVICE top
_newType = serviceType;
_newServiceName = null;
_newPath = null;
_message = this.r3provider.getR3TextRes().iSucceedMoveService;
}else if((r3CompareCaseString(roleType, this.state.selected.type) || r3CompareCaseString(policyType, this.state.selected.type) || r3CompareCaseString(resourceType, this.state.selected.type)) && !r3IsEmptyString(this.state.selected.service)){
// now "SERVICE > service name > ROLE/POLICY/RESOURCE..."
if(r3IsEmptyString(this.state.selected.path)){
// now "SERVICE > service name > ROLE/POLICY/RESOURCE", move to "SERVICE > service name"
_newType = serviceType;
_newServiceName = this.state.selected.service;
_newPath = null;
_message = this.r3provider.getR3TextRes().iSucceedMoveServiceName;
}else{
// now "SERVICE > service name > ROLE/POLICY/RESOURCE > path"
separatorPos = this.state.selected.path.lastIndexOf('/');
if(-1 === separatorPos){
// now "SERVICE > service name > ROLE/POLICY/RESOURCE > path", move to "SERVICE > service name > ROLE/POLICY/RESOURCE"
_newType = this.state.selected.type;
_newServiceName = this.state.selected.service;
_newPath = null;
_message = this.r3provider.getR3TextRes().iSucceedMoveType;
}else{
// now "SERVICE > service name > ROLE/POLICY/RESOURCE > path/path...", move to upper path
_newType = this.state.selected.type;
_newServiceName = this.state.selected.service;
_newPath = this.state.selected.path.substr(0, separatorPos);
_message = this.r3provider.getR3TextRes().iSucceedChangePath;
}
}
}else{
// now "ROLE/POLICY/RESOURCE > path"
separatorPos = this.state.selected.path.lastIndexOf('/');
if(-1 === separatorPos){
// now "ROLE/POLICY/RESOURCE > path", move to "ROLE/POLICY/RESOURCE"
_newType = this.state.selected.type;
_newServiceName = null;
_newPath = null;
_message = this.r3provider.getR3TextRes().iSucceedMoveType;
}else{
// now "ROLE/POLICY/RESOURCE > path/path...", move to move to upper path
_newType = this.state.selected.type;
_newServiceName = null;
_newPath = this.state.selected.path.substr(0, separatorPos);
_message = this.r3provider.getR3TextRes().iSucceedChangePath;
}
}
// update all
this.updateStateAllParts(this.state.selected.tenant, _newServiceName, _newType, _newPath, false, _message);
}
//
// Handle Create Path
//
handleCreatePath(newPath, newAllPath)
{
console.info('CALL CREATE PATH : ' + newPath + '(' + newAllPath + ')');
let _path = newAllPath.trim();
this.r3provider.createEmptyData(this.state.selected.tenant, this.state.selected.type, _path, (error) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, null, this.state.selected.type, _path, false, this.r3provider.getR3TextRes().iSucceedCreatePath);
});
}
//
// Handle Check Confrict Path
//
handleCheckConflictPath(newCreatePath)
{
if(r3IsEmptyString(this.state.selected.type) || r3CompareCaseString(serviceType, this.state.selected.type) || !r3IsEmptyString(this.state.selected.service)){
//
// if type is ignore(not select any or not service type or under service), this function returns true.
// it means do not create new path.
//
return true;
}
for(let cnt = 0; cnt < this.state.mainTree.length; ++cnt){
if(this.state.selected.type === this.state.mainTree[cnt].path){
return this.findCheckConflictPath(this.state.mainTree[cnt].children, newCreatePath, true);
}
}
return false;
}
//
// Handle Check Confrict Service Name
//
handleCheckConflictServiceName(newServiceName)
{
if(!r3CompareCaseString(serviceType, this.state.selected.type) || !r3IsEmptyString(this.state.selected.service)){
//
// if type is ignore(not select service), this function returns true.
// it means do not create new service name.
//
return true;
}
for(let cnt = 0; cnt < this.state.mainTree.length; ++cnt){
if(r3CompareCaseString(serviceType, this.state.mainTree[cnt].path)){
return this.findCheckConflictPath(this.state.mainTree[cnt].children, newServiceName, false);
}
}
return false;
}
//
// Utility : find same path under items
//
findCheckConflictPath(items, itemPath, isCheckNest)
{
if(!r3IsSafeTypedEntity(items, 'array') || r3IsEmptyString(itemPath)){
return false;
}
for(let cnt = 0; cnt < items.length; ++cnt){
if(itemPath === items[cnt].path){
return true;
}
if(isCheckNest && this.findCheckConflictPath(items[cnt].children, itemPath)){
return true;
}
}
return false;
}
//
// Handle Delete path
//
handleDeletePath()
{
console.info('CALL DELETE PATH');
if(r3IsEmptyEntity(this.state.selected.path)){
return;
}
this.r3provider.removeData(this.state.selected.tenant, this.state.selected.type, this.state.selected.path, (error) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, this.state.selected.service, this.state.selected.type, null, false, this.r3provider.getR3TextRes().iSucceedDeletePath);
});
}
handleDeleteService(isServiceOwner, isServiceTenant)
{
console.info('CALL DELETE SERVICE');
if( r3IsEmptyString(this.state.selected.service) ||
!r3IsSafeTypedEntity(isServiceTenant, 'boolean')||
!r3IsSafeTypedEntity(isServiceOwner, 'boolean') )
{
return;
}
let _isServiceOwner = isServiceOwner;
let _isServiceTenant= isServiceTenant;
this.r3provider.removeService(this.state.selected.tenant, this.state.selected.service, isServiceTenant, (error) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
let _servicename;
let _type;
if(!_isServiceTenant){
// Case : remove service
_servicename = null;
_type = serviceType;
}else{
// Case : remove service tenant
if(_isServiceOwner){
_servicename = this.state.selected.service;
_type = serviceType;
}else{
_servicename = null;
_type = serviceType;
}
}
// update all
this.updateStateAllParts(this.state.selected.tenant, _servicename, _type, null, false, (_isServiceTenant ? this.r3provider.getR3TextRes().iSucceedDeleteServiceTenant : this.r3provider.getR3TextRes().iSucceedDeleteService));
});
}
//
// Handle Updating flag
//
handleContentUpdating(isUpdating)
{
if(r3IsSafeTypedEntity(isUpdating, 'boolean')){
this.contentUpdating = isUpdating;
}
}
//
// Handle Save
//
handleSave(data)
{
console.info('CALL SAVE DATA : ' + JSON.stringify(data));
this.r3provider.updateData(this.state.selected.tenant, this.state.selected.type, this.state.selected.path, data, (error) =>
{
// set off updating flag
//
// [NOTE]
// We need to chane status of updating because it can not be rolled back when this function is called.
//
this.handleContentUpdating(false);
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, this.state.selected.service, this.state.selected.type, this.state.selected.path, false, this.r3provider.getR3TextRes().iSucceedUpdate);
});
}
//
// Handle Save for Service
//
handleServiceSave(data)
{
console.info('CALL SERVICE SAVE DATA : ' + JSON.stringify(data));
this.r3provider.updateServiceData(this.state.selected.tenant, this.state.selected.service, data.tenant, true, data.verify, (error) =>
{
// set off updating flag
//
// [NOTE]
// We need to chane status of updating because it can not be rolled back when this function is called.
//
this.handleContentUpdating(false);
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, this.state.selected.service, this.state.selected.type, this.state.selected.path, false, this.r3provider.getR3TextRes().iSucceedUpdate);
});
}
//
// Handle Create for Service
//
handleCreateService(newServiceName, newVerify)
{
console.info('CALL CREATE SERVICE : Service Name=' + JSON.stringify(newServiceName) + ', Verify=' + JSON.stringify(newVerify));
let _newServiceName = newServiceName;
let _newVerify = newVerify;
this.r3provider.createInitializedService(this.state.selected.tenant, _newServiceName, _newVerify, (error) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, _newServiceName, serviceType, null, false, this.r3provider.getR3TextRes().iSucceedCreateService);
});
}
//
// Handle Create for Service Tenant
//
handleCreateServiceTenant(aliasRole)
{
console.info('CALL CREATE SERVICE/TENANT');
let _aliasRole = aliasRole;
this.r3provider.createServiceTenant(this.state.selected.tenant, this.state.selected.service, _aliasRole, (error) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
// update all
this.updateStateAllParts(this.state.selected.tenant, this.state.selected.service, serviceType, null, false, this.r3provider.getR3TextRes().iSucceedCreateServiceTenant);
});
}
//
// Handle Singin/Signout
//
handleSign(configName)
{
let type = this.r3provider.getR3Context().getSignInType();
if(signinUnscopedToken == type){
//
// Unscoped Token Login Type
//
let signurl = '';
if(this.r3provider.getR3Context().isLogin()){
if(!r3IsEmptyString(configName)){
console.info('Signout does not require config name, but ' + configName + ' is specified, it is ignored.');
}
configName = this.r3provider.getR3Context().getSafeConfigName();
signurl = this.r3provider.getR3Context().getSafeSignOutUrl(configName); // value is 'URL'
}else{
if(!r3IsEmptyString(configName)){
signurl = this.r3provider.getR3Context().getSafeSignInUrl(configName).url; // value is 'URL'
}else if(1 <= this.r3provider.getR3Context().getSafeConfigCount(true)){
let signinObj = this.r3provider.getR3Context().getSafeSignInUrl();
Object.keys(signinObj).forEach(function(_configName){
// Get first config name
if(r3IsEmptyString(configName)){
configName = _configName;
}
});
signurl = this.r3provider.getR3Context().getSafeSignInUrl(configName).url; // value is 'URL'
}else{
console.info('Signin URL does not find.');
}
}
window.location.href = signurl;
}else if(signinCredential == type){
//
// Credential Login Type
//
if(this.r3provider.getR3Context().isLogin()){
// reload application for sign out
this.componentReinitialize(false);
}else{
// popup direct signin dialog
this.updateState({
signinDialogOpen: true
});
}
}else{ //signinUnknownType
this.updateState(null, this.r3provider.getR3TextRes().eUnknownSignInType, errorType);
}
}
//
// Handle Open About Dialog
//
handleAbout(package_name)
{
if(!r3IsEmptyString(package_name) && !r3IsEmptyEntityObject(this.licensesObj, package_name)){
// Licenses
this.updateState({
aboutDialogOpen: true,
licensePackage: package_name,
licenseType: this.licensesObj[package_name].licenseType,
licenseText: this.licensesObj[package_name].licenseText,
r3VersionText: null,
mainTreeOpen: false
});
}else{
// About K2HR3
this.updateState({
aboutDialogOpen: true,
licensePackage: null,
licenseType: null,
licenseText: null,
r3VersionText: r3VersionString,
mainTreeOpen: false
});
}
}
//
// Handle Close About Dialog
//
handAboutDialogClose(event, reason) // eslint-disable-line no-unused-vars
{
this.updateState({
aboutDialogOpen: false,
licensePackage: null,
licenseType: null,
licenseText: null,
r3VersionText: null
});
}
//
// Handle Open Account Dialog
//
handleAccount()
{
this.updateState({
accountDialogOpen: true
});
}
//
// Handle Close Account Dialog
//
handAccountDialogClose(event, reason) // eslint-disable-line no-unused-vars
{
this.updateState({
accountDialogOpen: false
});
}
//
// Handle Close Direct SignIn Dialog
//
handSignInDialogClose(event, reason, doSignIn, username, passphrase)
{
if(doSignIn){
// [NOTE]
// username is not empty when this handler is called with signin type.
//
let _username = username.trim();
// Try to sign in
this.r3provider.getUnscopedUserToken(_username, passphrase, (error, token) =>
{
if(null !== error){
this.updateState(null, this.r3provider.getR3TextRes().eCommunication + error.message, errorType);
return;
}
this.componentReinitialize(true, _username, token);
});
}
this.updateState({
signinDialogOpen: false
});
}
//
// Callback from R3Provider for Progress
//
cbProgressControl(isDisplay)
{
if(this.progressDisplayFunc){
this.progressDisplayFunc(isDisplay);
}
}
//
// Callback from R3Progress for register object reference
//
cbRefRegister(func)
{
if(!r3IsSafeTypedEntity(func, 'function')){
console.error('call cbRefRegister with invalid function parameter.');
return;
}
this.progressDisplayFunc = func;
}
//
// Renders : Contents
//
getContent()
{
// always increments(32bit cycling)
if(R3Container.dispUnique < 0xffffffff){
++R3Container.dispUnique;
}else{
R3Container.dispUnique = 0;
}
if(r3CompareCaseString(resourceType, this.state.selected.type)){
if(!r3IsEmptyEntity(this.state.selected.path)){
return (
<Paper
sx={ this.sxClasses.paper }
>
<R3Resource
theme={ this.props.theme }
r3provider={ this.r3provider }
resource={ this.state.resource }
dispUnique={ R3Container.dispUnique }
onSave={ this.handleSave }
onUpdate={ this.handleContentUpdating }
isReadMode={ !r3IsEmptyString(this.state.selected.service) }
/>
</Paper>
);
}
}else if(r3CompareCaseString(roleType, this.state.selected.type)){
if(!r3IsEmptyEntity(this.state.selected.path)){
return (
<Paper
sx={ this.sxClasses.paper }
>
<R3Role
theme={ this.props.theme }
r3provider={ this.r3provider }
role={ this.state.role }
dispUnique={ R3Container.dispUnique }
onSave={ this.handleSave }
onUpdate={ this.handleContentUpdating }
isReadMode={ !r3IsEmptyString(this.state.selected.service) }
/>
</Paper>
);
}
}else if(r3CompareCaseString(policyType, this.state.selected.type)){
if(!r3IsEmptyEntity(this.state.selected.path)){
return (
<Paper
sx={ this.sxClasses.paper }
>
<R3Policy
theme={ this.props.theme }
r3provider={ this.r3provider }
policy={ this.state.policy }
dispUnique={ R3Container.dispUnique }
onSave={ this.handleSave }
onUpdate={ this.handleContentUpdating }
isReadMode={ !r3IsEmptyString(this.state.selected.service) }
/>
</Paper>
);
}
}else if(r3CompareCaseString(serviceType, this.state.selected.type)){
// content is displaied at only service owner
if(this.r3provider.checkServiceOwnerInTreeList(this.state.mainTree, this.state.selected.service)){
return (
<Paper
sx={ this.sxClasses.paper }
>
<R3Service
theme={ this.props.theme }
r3provider={ this.r3provider }
tenant={ this.state.selected.tenant.name }
service={ this.state.service }
dispUnique={ R3Container.dispUnique }
r3provider={ this.r3provider }
onSave={ this.handleServiceSave }
onUpdate={ this.handleContentUpdating }
/>
</Paper>
);
}
}else{
// Not selected
return;
}
}
//
// Renders
//
render()
{
let signinDialogMsg = (r3CompareCaseString('http', this.r3provider.getR3Context().getSafeApiScheme()) ? this.r3provider.getR3TextRes().wDeprecateAuth : '');
//
// Common context for all child components
//
const commonContext = { r3Context: this.r3provider.getR3Context() };
return (
<R3CommonContext.Provider
value={ commonContext }
>
<React.Fragment>
<R3AppBar
theme={ this.props.theme }
r3provider={ this.r3provider }
title={ this.props.title }
enDock={ this.state.mainTreeEndock }
isDocking={ this.state.mainTreeDocked }
licensesObj={ this.licensesObj }
onTreeDetach={ this.handleTreeDetach }
onOpenTree={ this.handleTreeOpen }
onCheckUpdating={ this.handleIsContentUpdating }
onAbout={ this.handleAbout }
onSign={ this.handleSign }
onAccount={ this.handleAccount }
/>
<Box>
<R3MainTree
theme={ this.props.theme }
r3provider={ this.r3provider }
title={ this.props.title }
enDock={ this.state.mainTreeEndock }
isDocking={ this.state.mainTreeDocked }
licensesObj={ this.licensesObj }
open={ this.state.mainTreeOpen }
editableLocalTenant={ this.state.useLocalTenant }
userName={ this.state.username }
tenants={ this.state.tenants }
treeList={ this.state.mainTree }
selectedTenant={ this.state.selected.tenant }
selectedType={ this.state.selected.type }
selectedService={ this.state.selected.service }
selectedPath={ this.state.selected.path }
onTenantChange={ this.handleTenantChange }
onLocalTenantCreate={ this.handleLocalTenantCreate }
onLocalTenantChange={ this.handleLocalTenantChange }
onLocalTenantDelete={ this.handleLocalTenantDelete }
onTypeItemChange={ this.handleTypeChange }
onListItemChange={ this.handleListItemChange }
onNameItemInServiceChange={ this.handleNameItemInServiceChange }
onTypeInServiceChange={ this.handleTypeInServiceChange }
onListItemInServiceChange={ this.handleListItemInServiceChange }
onPopupClose={ this.handleTreePopupClose }
onTreeDocking={ this.handleTreeDocking }
onCheckUpdating={ this.handleIsContentUpdating }
onAbout={ this.handleAbout }
/>
<Box>
<R3Toolbar
theme={ this.props.theme }
r3provider={ this.r3provider }
enDock={ this.state.mainTreeEndock }
toolbarData={ this.state.toolbarData }
onArrawUpward={ this.handleMoveToUpPath }
onCreatePath={ this.handleCreatePath }
onCheckPath={ this.handleCheckConflictPath }
onDeletePath={ this.handleDeletePath }
onCreateService={ this.handleCreateService }
onCreateServiceTenant={ this.handleCreateServiceTenant }
onCheckServiceName={ this.handleCheckConflictServiceName }
onDeleteService={ this.handleDeleteService }
onCheckUpdating={ this.handleIsContentUpdating }
/>
<R3MsgBox
theme={ this.props.theme }
message={ this.state.message }
/>
{ this.getContent() }
</Box>
</Box>
<R3AboutDialog
theme={ this.props.theme }
r3provider={ this.r3provider }
open={ this.state.aboutDialogOpen }
onClose={ this.handAboutDialogClose }
licensePackage={ this.state.licensePackage }
licenseType={ this.state.licenseType }
licenseText={ this.state.licenseText }
r3VersionText={ this.state.r3VersionText }
/>
<R3AccountDialog
theme={ this.props.theme }
r3provider={ this.r3provider }
open={ this.state.accountDialogOpen }
onClose={ this.handAccountDialogClose }
username={ this.state.username }
unscopedtoken={ this.state.unscopedtoken }
/>
<R3SigninDialog
theme={ this.props.theme }
r3provider={ this.r3provider }
open={ this.state.signinDialogOpen }
name={ null }
passphrase={ null }
message={ signinDialogMsg }
onClose={ this.handSignInDialogClose }
/>
<R3Progress
theme={ this.props.theme }
cbRefRegister={ this.cbRefRegister }
/>
</React.Fragment>
</R3CommonContext.Provider>
);
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noexpandtab sw=4 ts=4 fdm=marker
* vim<600: noexpandtab sw=4 ts=4
*/