Skip to content

Commit

Permalink
GUI Run logs page: share run modal - ALL_ROLES (#3399)
Browse files Browse the repository at this point in the history
* GUI Run logs page: share run modal - ALL_ROLES

* GUI Run logs page: share with preview - ROLE_ALL

* GUI Run logs page: role all - minor style adjustments

* GUI Run logs page: all roles - fix accessType validation

* GUI Run logs page: all roles - fix accessType validation

* GUI Run logs page: all roles - fix unnecessary import

* GUI Run logs page: all roles - refactoring

* GUI Run logs page: all roles - wrong copypaste fixed
  • Loading branch information
AleksandrGorodetskii authored Nov 8, 2023
1 parent 1495161 commit 90948e3
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 28 deletions.
37 changes: 32 additions & 5 deletions client/src/components/runs/logs/Log.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import pipelineRunFSBrowserCache from '../../../models/pipelines/PipelineRunFSBr
import PipelineRunCommit from '../../../models/pipelines/PipelineRunCommit';
import pipelines from '../../../models/pipelines/Pipelines';
import Roles from '../../../models/user/Roles';
import PipelineRunUpdateSids from '../../../models/pipelines/PipelineRunUpdateSids';
import PipelineRunUpdateSids, {AccessTypes} from '../../../models/pipelines/PipelineRunUpdateSids';
import {
stopRun,
canCommitRun,
Expand Down Expand Up @@ -73,7 +73,7 @@ import LoadingView from '../../special/LoadingView';
import AWSRegionTag from '../../special/AWSRegionTag';
import DataStorageList from '../controls/data-storage-list';
import CommitRunDialog from './forms/CommitRunDialog';
import ShareWithForm from './forms/ShareWithForm';
import ShareWithForm, {ROLE_ALL, shouldCombineRoles} from './forms/ShareWithForm';
import DockerImageLink from './DockerImageLink';
import {getResumeFailureReason} from '../utilities/map-resume-failure-reason';
import RunTags from '../run-tags';
Expand Down Expand Up @@ -308,6 +308,15 @@ class Logs extends localization.LocalizedReactComponent {
return false;
}

get combineRolesIntoAllRoles () {
const {run} = this.state;
const {runSids = []} = run || {};
return {
ssh: shouldCombineRoles(runSids, ROLE_ALL.includedRoles, AccessTypes.ssh),
endpoint: shouldCombineRoles(runSids, ROLE_ALL.includedRoles, AccessTypes.endpoint)
};
}

exportLog = async () => {
const {runId} = this.props;
try {
Expand Down Expand Up @@ -1670,8 +1679,24 @@ class Logs extends localization.LocalizedReactComponent {
roleModel.isOwner(run)
) {
let shareList = 'Not shared (click to configure)';
if ((runSids || []).length > 0) {
shareList = (runSids || [])
const {
ssh: combineSshRoles,
endpoint: combineEndpointRoles
} = this.combineRolesIntoAllRoles;
const filteredRunSids = combineSshRoles || combineEndpointRoles
? [ROLE_ALL, ...runSids]
.filter(({name, accessType}) => {
if (
(combineSshRoles && accessType === AccessTypes.ssh) ||
(combineEndpointRoles && accessType === AccessTypes.endpoint)
) {
return !ROLE_ALL.includedRoles.includes(name);
}
return true;
})
: runSids;
if (filteredRunSids.length > 0) {
shareList = filteredRunSids
.map((s, index, array) => {
return (
<span
Expand Down Expand Up @@ -2285,7 +2310,9 @@ class Logs extends localization.LocalizedReactComponent {
sids={(runSids || []).map(s => s)}
pending={this.state.operationInProgress}
onSave={this.operationWrapper(this.saveShareSids)}
onClose={this.closeShareDialog} />
onClose={this.closeShareDialog}
runSharing
/>
<CommitRunDialog
runId={this.props.runId}
defaultDockerImage={dockerImage}
Expand Down
100 changes: 77 additions & 23 deletions client/src/components/runs/logs/forms/ShareWithForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ function sortByOverlap (str1, str2, query) {
}
return 0;
}

export const ROLE_ALL = {
name: 'ALL ROLES',
includedRoles: ['ROLE_USER', 'ROLE_ADMIN', 'ROLE_ANONYMOUS_USER']
};

export function shouldCombineRoles (sids, combinableRoles, accessType) {
if (!sids || !combinableRoles || !accessType) {
return false;
}
return combinableRoles
.every(roleName => !!sids
.find((role) => !role.isPrincipal &&
role.accessType === accessType &&
role.name === roleName
)
);
};

@observer
export default class ShareWithForm extends React.Component {
static propTypes = {
Expand All @@ -49,7 +68,8 @@ export default class ShareWithForm extends React.Component {
onClose: PropTypes.func,
visible: PropTypes.bool,
roles: PropTypes.array,
pending: PropTypes.bool
pending: PropTypes.bool,
runSharing: PropTypes.bool
};

state = {
Expand All @@ -65,6 +85,15 @@ export default class ShareWithForm extends React.Component {
operationInProgress: false
};

get combineRolesIntoAllRoles () {
const {sids} = this.state;
const {runSharing} = this.props;
return {
ssh: runSharing && shouldCombineRoles(sids, ROLE_ALL.includedRoles, AccessTypes.ssh),
endpoint: runSharing && shouldCombineRoles(sids, ROLE_ALL.includedRoles, AccessTypes.endpoint)
};
}

operationWrapper = (operation) => (...props) => {
this.setState({
operationInProgress: true
Expand Down Expand Up @@ -142,15 +171,16 @@ export default class ShareWithForm extends React.Component {
)
: [];
if (this.groupFind && !this.groupFind.pending && !this.groupFind.error) {
return [
...new Set(
[
...roles,
...(this.groupFind.value || []).map(g => g)]
)
].sort((u1, u2) => sortByOverlap(u1, u2, query));
const set = [...new Set([
...(this.props.runSharing ? [ROLE_ALL.name] : []),
...roles,
...(this.groupFind.value || []).map(g => g)
])];
return set
.sort((u1, u2) => sortByOverlap(u1, u2, query));
}
return [...roles].sort((u1, u2) => sortByOverlap(u1, u2, query));
return [...roles]
.sort((u1, u2) => sortByOverlap(u1, u2, query));
};

openFindUserDialog = () => {
Expand All @@ -164,7 +194,7 @@ export default class ShareWithForm extends React.Component {
onSelectUser = async () => {
const {userSearchString} = this.state;
const selectedUser = userSearchString ? userSearchString.trim() : null;
await this.grantPermission(selectedUser, true);
this.grantPermission(selectedUser, true);
this.closeFindUserDialog();
};

Expand All @@ -182,11 +212,15 @@ export default class ShareWithForm extends React.Component {
const [role] = this.props.roles
.filter(r => !r.predefined && this.splitRoleName(r.name) === selectedGroup);
const roleName = role ? role.name : selectedGroup;
await this.grantPermission(roleName, false);
if (roleName === ROLE_ALL.name) {
ROLE_ALL.includedRoles.forEach(role => this.grantPermission(role, false));
} else {
this.grantPermission(roleName, false);
}
this.closeFindGroupDialog();
};

grantPermission = async (name, isPrincipal) => {
grantPermission = (name, isPrincipal) => {
if (name) {
const sids = this.state.sids;
const [sidItem] = sids.filter(s => {
Expand All @@ -207,17 +241,15 @@ export default class ShareWithForm extends React.Component {

removeUserOrGroupClicked = (item) => async (event) => {
event.stopPropagation();
const sids = this.state.sids;
const [sidItem] = sids.filter(s => {
return s.isPrincipal === item.isPrincipal && s.name.toLowerCase() === item.name.toLowerCase();
});
if (sidItem) {
const index = sids.indexOf(sidItem);
if (index >= 0) {
sids.splice(index, 1);
this.setState({sids});
const {sids} = this.state;
const filterSids = ({name, isPrincipal}) => {
if (item.name === ROLE_ALL.name) {
return !ROLE_ALL.includedRoles.includes(name);
}
}
return !(name.toLowerCase() === item.name.toLowerCase() &&
isPrincipal === item.isPrincipal);
};
this.setState({sids: sids.filter(filterSids)});
};

renderUserName = (user) => {
Expand Down Expand Up @@ -326,9 +358,31 @@ export default class ShareWithForm extends React.Component {
</Col>
</Row>
);
const data = this.state.sids.map((p, index) => {
let data = this.state.sids.map((p, index) => {
return {...p, id: index};
});
const {
ssh: combineSshRoles,
endpoint: combineEndpointRoles
} = this.combineRolesIntoAllRoles;
if (combineSshRoles || combineEndpointRoles) {
data = [
...data,
{
...ROLE_ALL,
key: ROLE_ALL.name,
id: data.length
}
].filter(({name, accessType}) => {
if (
(combineSshRoles && accessType === AccessTypes.ssh) ||
(combineEndpointRoles && accessType === AccessTypes.endpoint)
) {
return !ROLE_ALL.includedRoles.includes(name);
}
return true;
});
}
return (
<Table
className={styles.table}
Expand Down

0 comments on commit 90948e3

Please sign in to comment.