mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-30 10:58:23 -05:00
Merge pull request #6078 from seotts/use-host-in-api-response
Use studio "host" in state, and accept "host" from api
This commit is contained in:
commit
be0144618d
9 changed files with 21 additions and 21 deletions
|
@ -3,7 +3,7 @@ const {selectUserId, selectIsAdmin, selectIsSocial,
|
||||||
selectHasFetchedSession, selectStudioCommentsGloballyEnabled} = require('./session');
|
selectHasFetchedSession, selectStudioCommentsGloballyEnabled} = require('./session');
|
||||||
|
|
||||||
// Fine-grain selector helpers - not exported, use the higher level selectors below
|
// Fine-grain selector helpers - not exported, use the higher level selectors below
|
||||||
const isHost = state => selectUserId(state) === state.studio.owner;
|
const isHost = state => selectUserId(state) === state.studio.host;
|
||||||
const isCurator = state => state.studio.curator;
|
const isCurator = state => state.studio.curator;
|
||||||
const isManager = state => state.studio.manager || isHost(state);
|
const isManager = state => state.studio.manager || isHost(state);
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ const selectCanRemoveCurator = (state, username) => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
const selectCanRemoveManager = (state, managerId) =>
|
const selectCanRemoveManager = (state, managerId) =>
|
||||||
!selectIsMuted(state) && (selectIsAdmin(state) || isManager(state)) && managerId !== state.studio.owner;
|
!selectIsMuted(state) && (selectIsAdmin(state) || isManager(state)) && managerId !== state.studio.host;
|
||||||
const selectCanPromoteCurators = state => !selectIsMuted(state) && isManager(state);
|
const selectCanPromoteCurators = state => !selectIsMuted(state) && isManager(state);
|
||||||
|
|
||||||
const selectCanTransfer = (state, managerId) => {
|
const selectCanTransfer = (state, managerId) => {
|
||||||
|
@ -61,7 +61,7 @@ const selectCanTransfer = (state, managerId) => {
|
||||||
if (state.studio.classroomId !== null) return false;
|
if (state.studio.classroomId !== null) return false;
|
||||||
if (selectIsMuted(state)) return false; // Muted users cannot transfer studios.
|
if (selectIsMuted(state)) return false; // Muted users cannot transfer studios.
|
||||||
if (state.studio.managers > 1) { // If there is more than one manager,
|
if (state.studio.managers > 1) { // If there is more than one manager,
|
||||||
if (managerId === state.studio.owner) { // and the selected manager is the current owner/host,
|
if (managerId === state.studio.host) { // and the selected manager is the current host,
|
||||||
if (isHost(state)) return true; // Owner/host can transfer
|
if (isHost(state)) return true; // Owner/host can transfer
|
||||||
if (selectIsAdmin(state)) return true; // Admin can transfer
|
if (selectIsAdmin(state)) return true; // Admin can transfer
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ const getInitialState = () => ({
|
||||||
image: '',
|
image: '',
|
||||||
followers: 0,
|
followers: 0,
|
||||||
managers: 0,
|
managers: 0,
|
||||||
owner: null,
|
host: null,
|
||||||
public: null,
|
public: null,
|
||||||
|
|
||||||
// BEWARE: classroomId is only loaded if the user is an educator or admin
|
// BEWARE: classroomId is only loaded if the user is an educator or admin
|
||||||
|
@ -135,7 +135,7 @@ const getInfo = () => ((dispatch, getState) => {
|
||||||
followers: body.stats.followers,
|
followers: body.stats.followers,
|
||||||
managers: body.stats.managers,
|
managers: body.stats.managers,
|
||||||
projectCount: body.stats.projects,
|
projectCount: body.stats.projects,
|
||||||
owner: body.owner,
|
host: body.host || body.owner, // TODO: Remove owner once api updated
|
||||||
public: body.public
|
public: body.public
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -218,7 +218,7 @@ const transferHost = (password, newHostName, newHostId) =>
|
||||||
}, (err, body, res) => {
|
}, (err, body, res) => {
|
||||||
const error = normalizeError(err, body, res);
|
const error = normalizeError(err, body, res);
|
||||||
if (error) return reject(error);
|
if (error) return reject(error);
|
||||||
dispatch(setInfo({owner: newHostId}));
|
dispatch(setInfo({host: newHostId}));
|
||||||
return resolve();
|
return resolve();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -202,7 +202,7 @@ TransferHostConfirmation.propTypes = {
|
||||||
|
|
||||||
const connectedConfirmationStep = connect(
|
const connectedConfirmationStep = connect(
|
||||||
state => ({
|
state => ({
|
||||||
hostId: state.studio.owner,
|
hostId: state.studio.host,
|
||||||
...managers.selector(state)
|
...managers.selector(state)
|
||||||
}), {
|
}), {
|
||||||
handleTransferHost: transferHost,
|
handleTransferHost: transferHost,
|
||||||
|
|
|
@ -107,7 +107,7 @@ TransferHostSelection.propTypes = {
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
state => ({
|
state => ({
|
||||||
hostId: state.studio.owner,
|
hostId: state.studio.host,
|
||||||
...managers.selector(state)
|
...managers.selector(state)
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,7 @@ const ManagerTile = connect(
|
||||||
canPromote: false,
|
canPromote: false,
|
||||||
canTransferHost: selectCanTransfer(state, ownProps.id) &&
|
canTransferHost: selectCanTransfer(state, ownProps.id) &&
|
||||||
selectStudioTransferLaunched(state),
|
selectStudioTransferLaunched(state),
|
||||||
isCreator: state.studio.owner === ownProps.id,
|
isCreator: state.studio.host === ownProps.id,
|
||||||
studioTransferLaunched: selectStudioTransferLaunched(state)
|
studioTransferLaunched: selectStudioTransferLaunched(state)
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"invited": true
|
"invited": true
|
||||||
},
|
},
|
||||||
"creator1": {
|
"creator1": {
|
||||||
"owner": 1
|
"host": 1
|
||||||
},
|
},
|
||||||
"openToAll": {
|
"openToAll": {
|
||||||
"openToAll": true
|
"openToAll": true
|
||||||
|
|
|
@ -415,7 +415,7 @@ describe('transferHost', () => {
|
||||||
studio: {
|
studio: {
|
||||||
id: 123123,
|
id: 123123,
|
||||||
managers: 3,
|
managers: 3,
|
||||||
owner: 'oldHost'
|
host: 'oldHost'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -427,7 +427,7 @@ describe('transferHost', () => {
|
||||||
await store.dispatch(transferHost('password', 'newHostName', 'newHostId'));
|
await store.dispatch(transferHost('password', 'newHostName', 'newHostId'));
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(api.mock.calls[0][0].uri).toBe('/studios/123123/transfer/newHostName');
|
expect(api.mock.calls[0][0].uri).toBe('/studios/123123/transfer/newHostName');
|
||||||
expect(state.studio.owner).toBe('newHostId');
|
expect(state.studio.host).toBe('newHostId');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of permissions issue', async () => {
|
test('error because of permissions issue', async () => {
|
||||||
|
@ -437,7 +437,7 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.PERMISSION);
|
.rejects.toBe(Errors.PERMISSION);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of authorization issue', async () => {
|
test('error because of authorization issue', async () => {
|
||||||
|
@ -447,7 +447,7 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.PERMISSION);
|
.rejects.toBe(Errors.PERMISSION);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of issue with new host', async () => {
|
test('error because of issue with new host', async () => {
|
||||||
|
@ -457,7 +457,7 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.CANNOT_BE_HOST);
|
.rejects.toBe(Errors.CANNOT_BE_HOST);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of incorrect password', async () => {
|
test('error because of incorrect password', async () => {
|
||||||
|
@ -467,7 +467,7 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.PASSWORD);
|
.rejects.toBe(Errors.PASSWORD);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of too many password attempts', async () => {
|
test('error because of too many password attempts', async () => {
|
||||||
|
@ -477,7 +477,7 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.PASSWORD_ATTEMPT_LIMIT);
|
.rejects.toBe(Errors.PASSWORD_ATTEMPT_LIMIT);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error because of rate limit', async () => {
|
test('error because of rate limit', async () => {
|
||||||
|
@ -487,6 +487,6 @@ describe('transferHost', () => {
|
||||||
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
await expect(store.dispatch(transferHost('password', 'newHostName', 'newHostId')))
|
||||||
.rejects.toBe(Errors.RATE_LIMIT);
|
.rejects.toBe(Errors.RATE_LIMIT);
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
expect(state.studio.owner).toBe('oldHost');
|
expect(state.studio.host).toBe('oldHost');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -411,7 +411,7 @@ describe('studio members', () => {
|
||||||
['muted logged in', false]
|
['muted logged in', false]
|
||||||
])('%s: %s', (role, expected) => {
|
])('%s: %s', (role, expected) => {
|
||||||
setStateByRole(role);
|
setStateByRole(role);
|
||||||
state.studio = {...state.studio, owner: 'the creator'};
|
state.studio = {...state.studio, host: 'the creator'};
|
||||||
expect(selectCanRemoveManager(state, 'the creator')).toBe(expected);
|
expect(selectCanRemoveManager(state, 'the creator')).toBe(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -449,12 +449,12 @@ describe('studio members', () => {
|
||||||
setStateByRole(role);
|
setStateByRole(role);
|
||||||
state.studio = {...state.studio, managers: 2, classroomId: null};
|
state.studio = {...state.studio, managers: 2, classroomId: null};
|
||||||
// Only admin and host see the option to transfer the current host
|
// Only admin and host see the option to transfer the current host
|
||||||
expect(selectCanTransfer(state, state.studio.owner)).toBe(expected);
|
expect(selectCanTransfer(state, state.studio.host)).toBe(expected);
|
||||||
// Nobody sees the option to transfer a manager who is not the host
|
// Nobody sees the option to transfer a manager who is not the host
|
||||||
expect(selectCanTransfer(state, 123)).toBe(false);
|
expect(selectCanTransfer(state, 123)).toBe(false);
|
||||||
// Nobody can transfer classroom studios
|
// Nobody can transfer classroom studios
|
||||||
state.studio = {...state.studio, classroomId: 1};
|
state.studio = {...state.studio, classroomId: 1};
|
||||||
expect(selectCanTransfer(state, state.studio.owner)).toBe(false);
|
expect(selectCanTransfer(state, state.studio.host)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue