blob: 3809f9fd6e25031b1a0252a155d28bed17d7a171 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Permissions actions, selectors, and reducers organized into
* a single Redux "Duck" that manages updating and retrieving permissions state
* on the frontend.
*
* The Permissions data is stored in a normalized format.
* `permissions` stores all PermissionSets[] indexed by resource name.
*
* Reference: https://github.com/erikras/ducks-modular-redux
*/
import {combineReducers} from 'redux';
import {createReducer, createRequestReducer} from './redux-helpers.js';
import {prpcClient} from 'prpc-client-instance.js';
import 'shared/typedef.js';
/** @typedef {import('redux').AnyAction} AnyAction */
// Permissions
// Field Permissions
export const FIELD_DEF_EDIT = 'FIELD_DEF_EDIT';
export const FIELD_DEF_VALUE_EDIT = 'FIELD_DEF_VALUE_EDIT';
// Actions
export const BATCH_GET_START = 'permissions/BATCH_GET_START';
export const BATCH_GET_SUCCESS = 'permissions/BATCH_GET_SUCCESS';
export const BATCH_GET_FAILURE = 'permissions/BATCH_GET_FAILURE';
/* State Shape
{
byName: Object<string, PermissionSet>,
requests: {
batchGet: ReduxRequestState,
},
}
*/
// Reducers
/**
* All PermissionSets indexed by resource name.
* @param {Object<string, PermissionSet>} state The existing items.
* @param {AnyAction} action
* @param {Array<PermissionSet>} action.permissionSets
* @return {Object<string, PermissionSet>}
*/
export const byNameReducer = createReducer({}, {
[BATCH_GET_SUCCESS]: (state, {permissionSets}) => {
const newState = {...state};
for (const permissionSet of permissionSets) {
newState[permissionSet.resource] = permissionSet;
}
return newState;
},
});
const requestsReducer = combineReducers({
batchGet: createRequestReducer(
BATCH_GET_START, BATCH_GET_SUCCESS, BATCH_GET_FAILURE),
});
export const reducer = combineReducers({
byName: byNameReducer,
requests: requestsReducer,
});
// Selectors
/**
* Returns all the PermissionSets in the store as a mapping.
* @param {any} state
* @return {Object<string, PermissionSet>}
*/
export const byName = (state) => state.permissions.byName;
/**
* Returns the Permissions requests.
* @param {any} state
* @return {Object<string, ReduxRequestState>}
*/
export const requests = (state) => state.permissions.requests;
// Action Creators
/**
* Action creator to fetch PermissionSets.
* @param {Array<string>} names The resource names to get.
* @return {function(function): Promise<Array<PermissionSet>>}
*/
export const batchGet = (names) => async (dispatch) => {
dispatch({type: BATCH_GET_START});
try {
/** @type {{permissionSets: Array<PermissionSet>}} */
const {permissionSets} = await prpcClient.call(
'monorail.v3.Permissions', 'BatchGetPermissionSets', {names});
for (const permissionSet of permissionSets) {
if (!permissionSet.permissions) {
permissionSet.permissions = [];
}
}
dispatch({type: BATCH_GET_SUCCESS, permissionSets});
return permissionSets;
} catch (error) {
dispatch({type: BATCH_GET_FAILURE, error});
};
};