Skip to content

Commit

Permalink
limit total pins created per user
Browse files Browse the repository at this point in the history
  • Loading branch information
Dereje1 committed Apr 9, 2024
1 parent 42724c7 commit 14654ff
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 5 deletions.
13 changes: 9 additions & 4 deletions client/src/components/mypins/mypins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ interface MypinsState {
displaySetting: string,
nameChangeFormIsShowing: boolean,
totalAiGenratedImages: number,
totalPinsOwned: number,
}

export class Mypins extends Component<MypinsProps, MypinsState> {
Expand All @@ -51,7 +52,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
displaySetting: 'created',
nameChangeFormIsShowing: false,
totalAiGenratedImages: 0,

totalPinsOwned: 0,
};
}

Expand All @@ -62,6 +63,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
pinList: profilePins,
ready: true,
totalAiGenratedImages,
totalPinsOwned: profilePins.filter((pin: PinType) => Boolean(pin.owns)).length,
});
}

Expand All @@ -88,7 +90,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {

// adds a new pin to the db
async addPin(pinJSON: {imgDescription: string, imgLink: string | ArrayBuffer}) {
const { pinList } = this.state;
const { pinList, totalPinsOwned } = this.state;
const { user: { displayName, service, userId } } = this.props;
this.setState({ ready: false });
const newPin = await RESTcall({
Expand All @@ -108,6 +110,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
ready: true,
displayPinCreate: false,
displaySetting: 'created',
totalPinsOwned: totalPinsOwned + 1,
});
}

Expand All @@ -119,12 +122,13 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
}

deletePic({ _id, owns }: {_id: string, owns: boolean}) {
const { pinList, displayPinCreate } = this.state;
const { pinList, displayPinCreate, totalPinsOwned } = this.state;
if (displayPinCreate) return;
this.setState({
pinList: pinList.filter((p) => p._id !== _id),
showDeleteImageModal: false,
deletableImgInfo: null,
totalPinsOwned: owns ? totalPinsOwned - 1 : totalPinsOwned,
}, async () => {
await RESTcall({
address: owns ? `/api/${_id}` : `/api/unpin/${_id}`,
Expand All @@ -138,7 +142,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
const {
displayPinCreate, showDeleteImageModal, deletableImgInfo,
pinList, ready, displaySetting,
nameChangeFormIsShowing, totalAiGenratedImages,
nameChangeFormIsShowing, totalAiGenratedImages, totalPinsOwned,
} = this.state;
if (!authenticated) return null;
if (!ready) return <Loading />;
Expand Down Expand Up @@ -178,6 +182,7 @@ export class Mypins extends Component<MypinsProps, MypinsState> {
aria-label="add"
onClick={() => this.pinForm()}
sx={{ marginTop: 1, zIndex: 1 }}
disabled={totalPinsOwned >= 10}
>
<AddIcon fontSize="large" />
</Fab>
Expand Down
7 changes: 6 additions & 1 deletion server/controllers/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export const addPin = async (req: Request, res: genericResponseType) => {
const { imgLink: originalImgLink } = req.body;
debug(`Creating new pin for userId -> ${userId}`);
try {
// check if pin limit has been reached
const createdPins = await pins.find({ owner: userId }).exec();
if (createdPins.length >= 10) {
throw new Error(`UserID: ${userId} has reached the pin creation limit - aborted!`);
}
const newImgLink = await uploadImageToS3({
originalImgLink, userId, displayName, service,
});
Expand All @@ -64,7 +69,7 @@ export const addPin = async (req: Request, res: genericResponseType) => {
debug(`${displayName} added pin ${addedpin.imgDescription}`);
res.json(addedpin);
} catch (error) {
debug(`Error creating new pin for userId -> ${userId}`);
debug(`Error creating new pin for userId -> ${userId} Error: ${error}`);
res.json(error);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ exports[`The Mypins component landing page will render message if no pins create
<ForwardRef(Fab)
aria-label="add"
color="default"
disabled={false}
id="createpin"
onClick={[Function]}
sx={
Expand Down Expand Up @@ -151,6 +152,7 @@ exports[`The Mypins component landing page will render message if no pins saved
<ForwardRef(Fab)
aria-label="add"
color="default"
disabled={false}
id="createpin"
onClick={[Function]}
sx={
Expand Down Expand Up @@ -246,6 +248,7 @@ exports[`The Mypins component landing page will render pins if found 1`] = `
<ForwardRef(Fab)
aria-label="add"
color="default"
disabled={false}
id="createpin"
onClick={[Function]}
sx={
Expand Down
8 changes: 8 additions & 0 deletions tests/client/src/components/mypins/mypins.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ describe('The Mypins component', () => {
expect(wrapper.state().displayPinCreate).toBe(true);
});

test('Will disable the pin create form if pins owned limit reached', async () => {
const wrapper = shallow<Mypins>(<Mypins {...props} />);
await Promise.resolve();
wrapper.setState({ totalPinsOwned: 10 });
const form = wrapper.find({ id: 'createpin' });
expect(form.props().disabled).toBe(true);
});

test('Will cancel pin delete on alert', async () => {
const wrapper = shallow<Mypins>(<Mypins {...props} />);
wrapper.setState({
Expand Down
35 changes: 35 additions & 0 deletions tests/server/controllers/post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ jest.mock('openai', () => jest.fn(() => mockOpenAiInstance));

/* Mongoose mocks */
const setupMocks = (response: PopulatedPinType[] | unknown = rawPinsStub) => {
pins.find = jest.fn().mockImplementation(
() => ({
exec: jest.fn().mockResolvedValue([]),
}),
);
pins.create = jest.fn().mockResolvedValue(response);
pins.findByIdAndUpdate = jest.fn().mockResolvedValue([]);
savedTags.create = jest.fn().mockResolvedValue([]);
Expand Down Expand Up @@ -330,7 +335,37 @@ describe('Adding a pin', () => {
expect(savedTags.create).toHaveBeenNthCalledWith(2, { tag: 'TEST-LABEL-B' });
});

test('will respond with error if pin creation limit has been reached', async () => {
const req = {
user,
body: {
owner: {
name: 'tester-twitter',
service: 'twitter',
id: user._id,
},
imgDescription: 'description-4',
imgLink: 'https://stub-4',
_id: 123,
},
};
jest.clearAllMocks();
pins.find = jest.fn().mockImplementation(
() => ({
exec: jest.fn().mockResolvedValue([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
}),
);
await addPin(req as genericRequest, res as unknown as Response);
expect(pins.create).toHaveBeenCalledTimes(0);
expect(res.json).toHaveBeenCalledWith(Error('UserID: 5cad310f7672ca00146485a8 has reached the pin creation limit - aborted!'));
});

test('will respond with error if POST is rejected', async () => {
pins.find = jest.fn().mockImplementation(
() => ({
exec: jest.fn().mockResolvedValue([]),
}),
);
pins.create = jest.fn().mockRejectedValue(new Error('Mocked rejection'));
const req = {
user,
Expand Down

0 comments on commit 14654ff

Please sign in to comment.