1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-23 20:37:42 +00:00
Files
seahub/frontend/src/pages/org-admin/org-saml-config.js

281 lines
10 KiB
JavaScript
Raw Normal View History

import React, { Fragment, Component } from 'react';
import { Row, Col, Label, Button } from 'reactstrap';
import MainPanelTopbar from './main-panel-topbar';
import toaster from '../../components/toast';
import Loading from '../../components/loading';
import { gettext, orgID, serviceURL } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import Section from './section';
import InputItem from './input-item';
import FileItem from './file-item';
class OrgSAMLConfig extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
errorMsg: '',
samlConfigID: '',
newUrlPrefix: '',
orgUrlPrefix: '',
metadataUrl: '',
singleSignOnService: '',
singleLogoutService: '',
validDays: '',
isBtnsShown: false,
};
}
toggleBtns = () => {
this.setState({isBtnsShown: !this.state.isBtnsShown});
}
hideBtns = () => {
if (!this.state.isBtnsShown) return;
if (this.state.newUrlPrefix !== this.state.orgUrlPrefix) {
this.setState({newUrlPrefix: this.state.orgUrlPrefix});
}
this.toggleBtns();
}
onSubmit = () => {
const newUrlPrefix = this.state.newUrlPrefix.trim();
if (newUrlPrefix !== this.state.orgUrlPrefix) {
this.updateUrlPrefix(newUrlPrefix);
}
this.toggleBtns();
}
inputOrgUrlPrefix = (e) => {
this.setState({newUrlPrefix: e.target.value});
}
inputMetadataUrl = (e) => {
this.setState({metadataUrl: e.target.value});
}
inputSingleSignOnService = (e) => {
this.setState({singleSignOnService: e.target.value});
}
inputSingleLogoutService = (e) => {
this.setState({singleLogoutService: e.target.value});
}
inputValidDays = (e) => {
this.setState({validDays: e.target.value});
}
componentDidMount() {
seafileAPI.orgAdminGetUrlPrefix(orgID).then((res) => {
this.setState({
newUrlPrefix: res.data.org_url_prefix,
orgUrlPrefix: res.data.org_url_prefix,
});
seafileAPI.orgAdminGetSamlConfig(orgID).then((res) => {
this.setState({
loading: false,
samlConfigID: res.data.saml_config.id || '',
metadataUrl: res.data.saml_config.metadata_url || '',
singleSignOnService: res.data.saml_config.single_sign_on_service || '',
singleLogoutService: res.data.saml_config.single_logout_service || '',
validDays: res.data.saml_config.valid_days || '',
});
}).catch(error => {
this.setState({
loading: false,
errorMsg: Utils.getErrorMsg(error, true),
});
});
}).catch(error => {
this.setState({
loading: false,
errorMsg: Utils.getErrorMsg(error, true),
});
});
}
updateUrlPrefix = (newUrlPrefix) => {
seafileAPI.orgAdminUpdateUrlPrefix(orgID, newUrlPrefix).then((res) => {
this.setState({
newUrlPrefix: res.data.org_url_prefix,
orgUrlPrefix: res.data.org_url_prefix,
});
toaster.success(gettext('Success'));
}).catch((error) => {
this.setState({newUrlPrefix: this.state.orgUrlPrefix});
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
postIdpCertificate = (file) => {
seafileAPI.orgAdminUploadIdpCertificate(orgID, file).then(() => {
toaster.success(gettext('Success'));
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
postIdpMetadataXml = (file) => {
seafileAPI.orgAdminUploadIdpMetadataXml(orgID, file).then(() => {
toaster.success(gettext('Success'));
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
addSamlConfig = () => {
const { metadataUrl, singleSignOnService, singleLogoutService, validDays } = this.state;
seafileAPI.orgAdminAddSamlConfig(orgID, metadataUrl, singleSignOnService, singleLogoutService, validDays).then((res) => {
this.setState({
samlConfigID: res.data.saml_config.id,
metadataUrl: res.data.saml_config.metadata_url,
singleSignOnService: res.data.saml_config.single_sign_on_service,
singleLogoutService: res.data.saml_config.single_logout_service,
validDays: res.data.saml_config.valid_days,
});
toaster.success(gettext('Success'));
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
updateSamlConfig = () => {
const { metadataUrl, singleSignOnService, singleLogoutService, validDays } = this.state;
seafileAPI.orgAdminUpdateSamlConfig(orgID, metadataUrl, singleSignOnService, singleLogoutService, validDays).then((res) => {
this.setState({
samlConfigID: res.data.saml_config.id,
metadataUrl: res.data.saml_config.metadata_url,
singleSignOnService: res.data.saml_config.single_sign_on_service,
singleLogoutService: res.data.saml_config.single_logout_service,
validDays: res.data.saml_config.valid_days,
});
toaster.success(gettext('Success'));
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
deleteSamlConfig = () => {
seafileAPI.orgAdminDeleteSamlConfig(orgID).then(() => {
this.setState({
samlConfigID: '',
metadataUrl: '',
singleSignOnService: '',
singleLogoutService: '',
validDays: '',
});
toaster.success(gettext('Success'));
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
render() {
const { loading, errorMsg, samlConfigID, newUrlPrefix, metadataUrl, singleSignOnService, singleLogoutService, validDays, isBtnsShown } = this.state;
return (
<Fragment>
<MainPanelTopbar />
<div className="main-panel-center flex-row">
<div className="cur-view-container">
<div className="cur-view-path">
<h3 className="sf-heading">{gettext('SAML config')}</h3>
</div>
<div className="cur-view-content container mw-100">
{loading && <Loading />}
{errorMsg && <p className="error text-center mt-4">{errorMsg}</p>}
{(!loading && !errorMsg) &&
<Fragment>
<Section headingText={gettext('Custom Login URL')}>
<Fragment>
<Row className="my-4">
<Col md="3">
<Label className="web-setting-label">{gettext('Your custom login URL')}</Label>
</Col>
<Col md="5">
{`${serviceURL}/org/custom/`}<input innerRef={input => {this.newInput = input;}} value={newUrlPrefix} onChange={this.inputOrgUrlPrefix} onFocus={this.toggleBtns} onBlur={this.hideBtns}></input>
<p className="small text-secondary mt-1">
{gettext('The custom part of the URL should be 6 to 20 characters, and can only contain alphanumeric characters and hyphens.')}
</p>
</Col>
{isBtnsShown &&
<Col md="4">
<Button className="sf2-icon-tick web-setting-icon-btn web-setting-icon-btn-submit" onMouseDown={this.onSubmit} title={gettext('Submit')}></Button>
<Button className="ml-1 sf2-icon-x2 web-setting-icon-btn web-setting-icon-btn-cancel" title={gettext('Cancel')}></Button>
</Col>
}
</Row>
</Fragment>
</Section>
<Section headingText={gettext('Manage SAML Config')}>
<Fragment>
<InputItem
value={metadataUrl}
changeValue={this.inputMetadataUrl}
displayName={gettext('App Federation Metadata URL')}
/>
<InputItem
value={singleSignOnService}
changeValue={this.inputSingleSignOnService}
displayName={gettext('Login URL')}
/>
<InputItem
value={singleLogoutService}
changeValue={this.inputSingleLogoutService}
displayName={gettext('Logout URL')}
/>
<InputItem
value={validDays}
changeValue={this.inputValidDays}
displayName={gettext('Valid Days (how long our metadata is valid)')}
/>
<Row className="my-4">
{samlConfigID ?
<Fragment>
<Col md="1">
<Button color="secondary" onClick={this.updateSamlConfig}>{gettext('Update')}</Button>
</Col>
<Col md="1">
<Button color="primary" onClick={this.deleteSamlConfig}>{gettext('Delete')}</Button>
</Col>
</Fragment> :
<Col md="1">
<Button color="secondary" onClick={this.addSamlConfig}>{gettext('Save')}</Button>
</Col>}
</Row>
</Fragment>
</Section>
<Section headingText={gettext('Upload IdP Files')}>
<Fragment>
<FileItem
postFile={this.postIdpCertificate}
displayName={gettext('IdP Certificate')}
/>
<FileItem
postFile={this.postIdpMetadataXml}
displayName={gettext('Federation Metadata XML')}
/>
</Fragment>
</Section>
</Fragment>
}
</div>
</div>
</div>
</Fragment>
);
}
}
export default OrgSAMLConfig;