Skip to content

Commit 0688f4d

Browse files
tom3qnicolodavis
andauthored
Include credentials in undo/redo actions (#595)
* Fix type of Plugin action The Plugin action is defined to contain credentials and its credentialed version is already defined in CredentialedActionShape. However, CredentialedActionShape.Any included ActionShape.Plugin instead. Use the one with credentials. * Include credentials in undo/redo actions If playing on a remote server, actions are validated wrt player credentials that are assumed to be inside action.payload.credentials: https://github.com/nicolodavis/boardgame.io/blob/v0.39.3/src/master/master.ts#L188 However, in case of undo and redo, the client sends an action that consists only of type: https://github.com/nicolodavis/boardgame.io/blob/v0.39.3/src/core/action-creators.ts#L97 Make it possible to undo/redo with a remote server and fix #593 by adding credentials to undo/redo actions. All the remaining actions without credentials are client-only, so remove them from CredentialedActionShape and make the master only accept CredentialedActionShape.Any in onUpdate(). Co-authored-by: Nicolo John Davis <[email protected]>
1 parent c5211c2 commit 0688f4d

4 files changed

Lines changed: 24 additions & 28 deletions

File tree

src/client/client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class _ClientImpl {
9898
this.store.dispatch(ActionCreators.reset(this.initialState));
9999
};
100100
this.undo = () => {
101-
this.store.dispatch(ActionCreators.undo());
101+
this.store.dispatch(ActionCreators.undo(playerID, credentials));
102102
};
103103
this.redo = () => {
104-
this.store.dispatch(ActionCreators.redo());
104+
this.store.dispatch(ActionCreators.redo(playerID, credentials));
105105
};
106106

107107
this.store = null;

src/core/action-creators.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,22 @@ export const reset = (state: State) => ({
9696

9797
/**
9898
* Used to undo the last move.
99+
* @param {string} playerID - The ID of the player making this action.
100+
* @param {string} credentials - (optional) The credentials for the player making this action.
99101
*/
100-
export const undo = () => ({
102+
export const undo = (playerID?: string | null, credentials?: string) => ({
101103
type: Actions.UNDO as typeof Actions.UNDO,
104+
payload: { type: null, args: null, playerID, credentials },
102105
});
103106

104107
/**
105108
* Used to redo the last undone move.
109+
* @param {string} playerID - The ID of the player making this action.
110+
* @param {string} credentials - (optional) The credentials for the player making this action.
106111
*/
107-
export const redo = () => ({
112+
export const redo = (playerID?: string | null, credentials?: string) => ({
108113
type: Actions.REDO as typeof Actions.REDO,
114+
payload: { type: null, args: null, playerID, credentials },
109115
});
110116

111117
/**

src/master/master.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,10 @@ export const isActionFromAuthenticPlayer = (
106106
/**
107107
* Remove player credentials from action payload
108108
*/
109-
const stripCredentialsFromAction = (
110-
action: CredentialedActionShape.Any | ActionShape.Any
111-
) => {
112-
if ('payload' in action && 'credentials' in action.payload) {
113-
// eslint-disable-next-line no-unused-vars
114-
const { credentials, ...payload } = action.payload;
115-
return { ...action, payload };
116-
}
117-
return action;
109+
const stripCredentialsFromAction = (action: CredentialedActionShape.Any) => {
110+
// eslint-disable-next-line no-unused-vars
111+
const { credentials, ...payload } = action.payload;
112+
return { ...action, payload };
118113
};
119114

120115
type AuthFn = (
@@ -170,16 +165,13 @@ export class Master {
170165
* along with a deltalog.
171166
*/
172167
async onUpdate(
173-
action: CredentialedActionShape.Any | ActionShape.Any,
168+
credAction: CredentialedActionShape.Any,
174169
stateID: number,
175170
gameID: string,
176171
playerID: string
177172
) {
178173
let isActionAuthentic;
179-
const credentials =
180-
'payload' in action && 'credentials' in action.payload
181-
? action.payload.credentials
182-
: undefined;
174+
const credentials = credAction.payload.credentials;
183175
if (IsSynchronous(this.storageAPI)) {
184176
const { metadata } = this.storageAPI.fetch(gameID, { metadata: true });
185177
const playerMetadata = getPlayerMetadata(metadata, playerID);
@@ -199,8 +191,7 @@ export class Master {
199191
return { error: 'unauthorized action' };
200192
}
201193

202-
action = stripCredentialsFromAction(action);
203-
194+
let action = stripCredentialsFromAction(credAction);
204195
const key = gameID;
205196

206197
let state: State;

src/types.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,16 +291,15 @@ export namespace CredentialedActionShape {
291291
export type AutomaticGameEvent = ReturnType<
292292
typeof ActionCreators.automaticGameEvent
293293
>;
294+
export type Undo = ReturnType<typeof ActionCreators.undo>;
295+
export type Redo = ReturnType<typeof ActionCreators.redo>;
294296
export type Any =
295297
| MakeMove
296298
| GameEvent
297299
| AutomaticGameEvent
298-
| ActionShape.Sync
299-
| ActionShape.Update
300-
| ActionShape.Reset
301-
| ActionShape.Undo
302-
| ActionShape.Redo
303-
| ActionShape.Plugin;
300+
| Undo
301+
| Redo
302+
| Plugin;
304303
}
305304

306305
export namespace ActionShape {
@@ -317,8 +316,8 @@ export namespace ActionShape {
317316
export type Sync = ReturnType<typeof ActionCreators.sync>;
318317
export type Update = ReturnType<typeof ActionCreators.update>;
319318
export type Reset = ReturnType<typeof ActionCreators.reset>;
320-
export type Undo = ReturnType<typeof ActionCreators.undo>;
321-
export type Redo = ReturnType<typeof ActionCreators.redo>;
319+
export type Undo = StripCredentials<CredentialedActionShape.Undo>;
320+
export type Redo = StripCredentials<CredentialedActionShape.Redo>;
322321
export type Any =
323322
| MakeMove
324323
| GameEvent

0 commit comments

Comments
 (0)