Skip to content

Commit

Permalink
Edit ship sheet sections (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
jarrod-lowe authored Oct 13, 2024
1 parent d21b213 commit 44c79dc
Show file tree
Hide file tree
Showing 15 changed files with 53 additions and 52 deletions.
15 changes: 3 additions & 12 deletions graphql/function/checkGameAccess/checkGameAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ export function request(
}

const identity = context.identity as AppSyncIdentityCognito;
if (!identity?.sub) {
util.error("Unauthorized: User ID is missing." as string);
}
if (!identity?.sub) util.unauthorized();

const id = context.args.input.gameId;
const key = {
Expand Down Expand Up @@ -42,15 +40,8 @@ export function response(context: ResponseContext): DataGame | undefined {
}

const identity = context.identity as AppSyncIdentityCognito;
if (!identity?.sub) {
util.error("Unauthorized: User ID is missing." as string);
}

if (!permitted(identity, context.result)) {
util.error(
"Unauthorized: User does not have access to the game." as string,
);
}
if (!identity?.sub) util.unauthorized();
if (!permitted(identity, context.result)) util.unauthorized();

context.stash.isFirefly = context.result.fireflyUserId === identity.sub;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,7 @@ export function response(
if (!context.result) util.unauthorized();
if (identity.sub != context.result.userId) util.unauthorized();

context.stash.playerType = context.result.type;

return context.result;
}
4 changes: 2 additions & 2 deletions graphql/function/checkShipSheetAccess/checkShipSheetAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ export function response(

if (!context.result) util.unauthorized();
if (context.result.type !== TypeShip) util.unauthorized();
console.error("HIT!");
console.error(context);

context.stash.playerType = context.result.type;

return context.result;
}
1 change: 1 addition & 0 deletions graphql/function/createSection/createSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function request(
createdAt: timestamp,
updatedAt: timestamp,
type: TypeSection,
playerType: context.stash.playerType,
}) as PutItemInputAttributeMap,
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { util, Context, AppSyncIdentityCognito } from "@aws-appsync/utils";
import type { DynamoDBUpdateItemRequest } from "@aws-appsync/utils/lib/resolver-return-types";
import { SheetSection, UpdateSectionInput } from "../../../appsync/graphql";
import { DDBPrefixGame, DDBPrefixSection } from "../../lib/constants";
import { DDBPrefixGame, DDBPrefixSection, TypeShip } from "../../lib/constants";

interface UpdateType {
updatedAt: string;
Expand Down Expand Up @@ -60,14 +60,14 @@ export function request(
SK: sk,
}),
condition: {
expression: "#SK = :SK AND #userId = :userId",
expression: "#userId = :userId OR #playerType = :playerType",
expressionNames: {
"#SK": "SK",
"#userId": "userId",
"#playerType": "playerType",
},
expressionValues: util.dynamodb.toMapValues({
":SK": sk,
":userId": identity.sub,
":playerType": TypeShip,
}),
},
update: {
Expand All @@ -80,6 +80,8 @@ export function request(

export function response(context: Context): SheetSection | null {
if (context.error) {
if (context.error.type === "DynamoDB:ConditionalCheckFailedException")
util.unauthorized();
util.error(context.error.message, context.error.type, context.result);
}
return context.result;
Expand Down
4 changes: 4 additions & 0 deletions terraform/module/wildsea/graphql.tf
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ locals {
type : "Mutation",
functions = ["checkPlayerSheetAccess", "checkShipSheetAccess", "createSection"]
}
updateSection = {
type : "Mutation",
functions = ["checkGameAccess", "updateSection"]
}
deletePlayer = {
type : "Mutation",
functions = ["checkPlayerSheetAccessWithFirefly", "findAllSections", "deletePlayer"]
Expand Down
21 changes: 13 additions & 8 deletions ui/src/baseSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ export interface BaseSectionContent<T extends BaseSectionItem> {

interface BaseSectionProps<T extends BaseSectionItem> {
section: SheetSection;
userSubject: string;
mayEditSheet: boolean;
renderItems: (
content: BaseSectionContent<T>,
userSubject: string,
sectionUserId: string,
mayEditSheet: boolean,
setContent: React.Dispatch<React.SetStateAction<BaseSectionContent<T>>>,
updateSection: (updatedSection: Partial<SheetSection>) => Promise<void>,
) => React.ReactNode;
Expand All @@ -33,11 +32,17 @@ interface BaseSectionProps<T extends BaseSectionItem> {
) => React.ReactNode;
}

export type SectionDefinition = {
section: SheetSection
mayEditSheet: boolean
onUpdate: (updatedSection: SheetSection) => void
}

export const BaseSection = <T extends BaseSectionItem>({
section,
userSubject,
mayEditSheet,
renderItems,
renderEditForm
renderEditForm,
}: BaseSectionProps<T>) => {
const [isEditing, setIsEditing] = useState(false);
const [content, setContent] = useState<BaseSectionContent<T>>(JSON.parse(section.content || '{}'));
Expand Down Expand Up @@ -92,12 +97,12 @@ export const BaseSection = <T extends BaseSectionItem>({
setIsEditing(false);
};

if (userSubject !== section.userId) {
if (!mayEditSheet) {
return (
<div className="section">
<h3>{sectionName}</h3>
<div className="section-items">
{renderItems(content, userSubject, section.userId, setContent, updateSection)}
{renderItems(content, mayEditSheet, setContent, updateSection)}
</div>
</div>
);
Expand Down Expand Up @@ -131,7 +136,7 @@ export const BaseSection = <T extends BaseSectionItem>({
setIsEditing(true);
}} /></h3>
<div className="section-items">
{renderItems(content, userSubject, section.userId, setContent, updateSection)}
{renderItems(content, mayEditSheet, setContent, updateSection)}
</div>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions ui/src/playerSheetTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TypeFirefly, TypeShip } from "../../graphql/lib/constants";
import { Section } from './section';
import { getSectionSeed, getSectionTypes } from './sectionRegistry';
import { useToast } from './notificationToast';
import { DragDropContext, Droppable, Draggable, DroppableProvided, DraggableProvided } from '@hello-pangea/dnd';
import { DragDropContext, Droppable, Draggable, DroppableProvided, DraggableProvided } from "@hello-pangea/dnd";
import Modal from 'react-modal';
import { DeletePlayerModal } from './deletePlayer';
import { DeleteGameModal } from './deleteGame';
Expand Down Expand Up @@ -157,7 +157,7 @@ export const PlayerSheetTab: React.FC<{ sheet: PlayerSheet, userSubject: string,
}
};

let deleteButtonId = "playerSheetTab.quitGameLabel";
let deleteButtonId = "playerSheetTab.quitLabel";
if (userSubject === sheet.fireflyUserId) deleteButtonId = "playerSheetTab.kickPlayerLabel";
if (sheet.type === TypeShip) deleteButtonId = "playerSheetTab.kickShipLabel";

Expand All @@ -173,7 +173,7 @@ export const PlayerSheetTab: React.FC<{ sheet: PlayerSheet, userSubject: string,
<Section
key={section.sectionId}
section={section}
userSubject={userSubject}
mayEditSheet={mayEditSheet}
onUpdate={(updatedSection) => {
const updatedSections = sheet.sections.map(s =>
s.sectionId === updatedSection.sectionId ? updatedSection : s
Expand Down
6 changes: 3 additions & 3 deletions ui/src/section.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { SheetSection } from "../../appsync/graphql";
import { getSectionComponent } from './sectionRegistry';
import { SectionDefinition } from './baseSection';

export const Section: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }> = ({ section, userSubject, onUpdate }) => {
export const Section: React.FC<SectionDefinition> = ({ section, mayEditSheet, onUpdate }) => {
const SectionComponent = getSectionComponent(section.sectionType);

if (!SectionComponent) {
return <div>Unsupported section type</div>;
}

return <SectionComponent section={section} userSubject={userSubject} onUpdate={onUpdate} />;
return <SectionComponent section={section} mayEditSheet={mayEditSheet} onUpdate={onUpdate} />;
};
9 changes: 4 additions & 5 deletions ui/src/sectionBurnable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { BaseSection, BaseSectionContent, BaseSectionItem } from './baseSection';
import { BaseSection, BaseSectionContent, BaseSectionItem, SectionDefinition } from './baseSection';
import { SheetSection } from "../../appsync/graphql";
import { FormattedMessage, useIntl } from 'react-intl';
import { v4 as uuidv4 } from 'uuid';
Expand Down Expand Up @@ -44,7 +44,7 @@ const BurnCheckbox: React.FC<{
);
};

export const SectionBurnable: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }> = (props) => {
export const SectionBurnable: React.FC<SectionDefinition> = (props) => {
const intl = useIntl();

const handleStateChange = async (
Expand Down Expand Up @@ -82,8 +82,7 @@ export const SectionBurnable: React.FC<{ section: SheetSection, userSubject: str

const renderItems = (
content: SectionTypeBurnable,
userSubject: string,
sectionUserId: string,
mayEditSheet: boolean,
setContent: React.Dispatch<React.SetStateAction<SectionTypeBurnable>>,
updateSection: (updatedSection: Partial<SheetSection>) => Promise<void>,
) => {
Expand All @@ -106,7 +105,7 @@ export const SectionBurnable: React.FC<{ section: SheetSection, userSubject: str
key={`${item.id}-${index}`}
state={state}
onClick={() => handleStateChange(item, index, content, setContent, updateSection)}
disabled={userSubject !== sectionUserId}
disabled={!mayEditSheet}
/>
))}
</>
Expand Down
9 changes: 4 additions & 5 deletions ui/src/sectionKeyValue.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { BaseSection, BaseSectionContent, BaseSectionItem } from './baseSection';
import { BaseSection, BaseSectionContent, BaseSectionItem, SectionDefinition } from './baseSection';
import { SheetSection } from "../../appsync/graphql";
import { useIntl } from 'react-intl';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -12,7 +12,7 @@ interface KeyValueItem extends BaseSectionItem {

type SectionTypeKeyValue = BaseSectionContent<KeyValueItem>;

export const SectionKeyValue: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }> = (props) => {
export const SectionKeyValue: React.FC<SectionDefinition> = (props) => {
const intl = useIntl();

const handleValueChange = async (
Expand All @@ -34,8 +34,7 @@ export const SectionKeyValue: React.FC<{ section: SheetSection, userSubject: str

const renderItems = (
content: SectionTypeKeyValue,
userSubject: string,
sectionUserId: string,
mayEditSheet: boolean,
setContent: React.Dispatch<React.SetStateAction<SectionTypeKeyValue>>,
updateSection: (updatedSection: Partial<SheetSection>) => Promise<void>,
) => {
Expand All @@ -50,7 +49,7 @@ export const SectionKeyValue: React.FC<{ section: SheetSection, userSubject: str
type="text"
value={item.value}
onChange={(e) => handleValueChange(item, e.target.value, content, setContent, updateSection)}
disabled={userSubject !== sectionUserId}
disabled={!mayEditSheet}
/>
)}
/>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/sectionRegistry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SectionKeyValue } from './sectionKeyValue';
import { SectionRichText } from './sectionRichText';

type SectionTypeConfig = {
component: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }>;
component: React.FC<{ section: SheetSection, mayEditSheet: boolean, onUpdate: (updatedSection: SheetSection) => void }>;
label: string; // i18n key for translation
seed?: any;
};
Expand Down
5 changes: 2 additions & 3 deletions ui/src/sectionRichText.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { BaseSection, BaseSectionContent, BaseSectionItem } from './baseSection';
import { SheetSection } from "../../appsync/graphql";
import { BaseSection, BaseSectionContent, BaseSectionItem, SectionDefinition } from './baseSection';
import ReactMarkdown from 'react-markdown';
import { SectionItemDescription } from './components/SectionItem';
import { useIntl } from 'react-intl';
Expand All @@ -11,7 +10,7 @@ interface RichTextItem extends BaseSectionItem {

type SectionTypeRichText = BaseSectionContent<RichTextItem>;

export const SectionRichText: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }> = (props) => {
export const SectionRichText: React.FC<SectionDefinition> = (props) => {
const intl = useIntl();

const renderItems = (
Expand Down
9 changes: 4 additions & 5 deletions ui/src/sectionTrackable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { BaseSection, BaseSectionContent, BaseSectionItem } from './baseSection';
import { BaseSection, BaseSectionContent, BaseSectionItem, SectionDefinition } from './baseSection';
import { SheetSection } from "../../appsync/graphql";
import { FormattedMessage, useIntl } from 'react-intl';
import { v4 as uuidv4 } from 'uuid';
Expand Down Expand Up @@ -32,7 +32,7 @@ const TickCheckbox: React.FC<{
);
};

export const SectionTrackable: React.FC<{ section: SheetSection, userSubject: string, onUpdate: (updatedSection: SheetSection) => void }> = (props) => {
export const SectionTrackable: React.FC<SectionDefinition> = (props) => {
const intl = useIntl();

const handleTickClick = async (
Expand Down Expand Up @@ -60,8 +60,7 @@ export const SectionTrackable: React.FC<{ section: SheetSection, userSubject: st

const renderItems = (
content: SectionTypeTrackable,
userSubject: string,
sectionUserId: string,
mayEditSheet: boolean,
setContent: React.Dispatch<React.SetStateAction<SectionTypeTrackable>>,
updateSection: (updatedSection: Partial<SheetSection>) => Promise<void>,
) => {
Expand All @@ -78,7 +77,7 @@ export const SectionTrackable: React.FC<{ section: SheetSection, userSubject: st
key={`${item.id}-${index}`}
state={index < item.ticked ? 'ticked' : 'unticked'}
onClick={() => handleTickClick(item, index, content, setContent, updateSection)}
disabled={userSubject !== sectionUserId}
disabled={!mayEditSheet}
/>
))}
</>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const messages = {
'playerSheetTab.addSection': 'Add a section',
'playerSheetTab.deleteSection': 'Delete a section',
'playerSheetTab.deleteSectionWarning': 'Deleting a section is permanent and cannot be undone. All data within the section will be lost.',
'playerSheetTab.quitGameLabel': 'Quit Game',
'playerSheetTab.quitLabel': 'Quit Game',
'playerSheetTab.kickShipLabel': 'Delete Ship',
'playerSheetTab.kickPlayerLabel': 'Kick Player',
'playerSheetTab.quitConfirmation': 'Are you sure you want to quit this game?',
Expand Down

0 comments on commit 44c79dc

Please sign in to comment.