constructor()

in lambda/api/src/app.ts [32:193]


  constructor(private opts: AppOptions, public expressApp: Express = express()) {

    const app = expressApp;

    app.use(cors({
      credentials: false,
      origin: [(opts.allowedOrigin)],
    }));

    app.use(json());
    app.use(urlencoded({extended: true}));

    app.use(eventContext());

    app.use(authorizationMiddleware({
      authorizationHeaderName: opts.authorizationHeaderName,
      supportedGroups: [
        opts.adminsGroupName,
        opts.usersGroupName,
      ],
      forceSignOutHandler: opts.forceSignOutHandler,
      allowedPaths: ["/"],
    }));

    /**
     * Ping
     */
    app.get("/", async (req: Request, res: Response) => {
      res.json({status: "ok"});
    });

    /**
     * List all pets
     */
    app.get("/pets", async (req: Request, res: Response) => {

      if (req.groups.has(opts.adminsGroupName)) {
        // if the user has the admin group, we return all pets
        res.json(await opts.storageService.getAllPets());
      } else {
        // otherwise, just owned pets (middleware ensure that the user is in either of the 2 groups)
        res.json(await opts.storageService.getAllPetsByOwner(req.username));
      }
    });

    /**
     * Get a pet
     */
    app.get("/pets/:petId", async (req: Request, res: Response) => {
      const petId = req.params.petId;

      const pet = await opts.storageService.getPet(petId);

      if (!pet) {
        res.status(404).json({error: `Pet with id ${petId} was not found`});
        return;
      }

      if (req.groups.has(opts.adminsGroupName) || pet.owner === req.username) {
        // if the pet is owned by the user or they are an admin, return it.
        res.json(pet);
      } else {
        res.status(403).json({error: `Unauthorized`});
      }
    });

    /**
     * Create a pet
     */
    app.post("/pets", async (req: Request, res: Response) => {

      const pet: Pet = req.body;

      // TODO: make sure body is parsed as JSON, post and put stopped working
      console.log("post /pets ", typeof pet, pet);

      if (pet.id) {
        res.status(400).json({error: "POST /pet auto assigns an id. In order to update use PUT /pet"});
        return;
      }

      // auto generate an ID
      pet.id = uuid4();
      // set the owner to the current user
      pet.owner = req.username;

      pet.ownerDisplayName = req.claims.email;

      await opts.storageService.savePet(pet);
      res.json(pet);
    });

    /**
     * Update a pet
     */
    app.put("/pets/:petId", async (req: Request, res: Response) => {

      const updatedPet: Pet = req.body;
      const petId = req.params.petId;

      if (!petId) {
        res.status(400).json({error: "Invalid request - missing Pet ID"});
        return;
      }
      if (!updatedPet) {
        res.status(400).json({error: "Invalid request - missing Pet"});
        return;
      }
      if (updatedPet.id !== petId) {
        res.status(400).json({error: "Invalid request - Pet.id doesn't match request param"});
        return;
      }
      const existingPet = await opts.storageService.getPet(petId);

      if (!existingPet) {
        res.status(404).json({error: `Pet with id ${petId} was not found`});
        return;
      }

      if (req.groups.has(opts.adminsGroupName)
        || updatedPet.owner === existingPet.owner && existingPet.owner === req.username) {
        // if the user is an admin, or the pet is owned by the owner and didn't change the owner, allow
        // only admin can change the owner
        await opts.storageService.savePet(updatedPet);
        res.json(updatedPet);

      } else {
        res.status(403).json({error: "Unauthorized"});
      }
    });

    /**
     * Delete a pet
     */
    app.delete("/pets/:petId", async (req: Request, res: Response) => {

      const petId = req.params.petId;
      const pet = await opts.storageService.getPet(petId);

      if (!pet) {
        res.status(404).json({error: `Pet with id ${petId} was not found`});
        return;
      }

      if (req.groups.has(opts.adminsGroupName) || pet.owner === req.username) {
        // if the pet is owned by the user or they are an admin, allow deleting it
        await opts.storageService.deletePet(petId);
        res.json(pet);
      } else {
        res.status(403).json({error: `Unauthorized`});
      }
    });

    app.post("/forceSignOut", async (req: Request, res: Response) => {
      // all tokens issued before this call will no longer be allowed to be used
      await opts.cognito.adminUserGlobalSignOut({Username: req.username, UserPoolId: opts.userPoolId}).promise();
      if (opts.forceSignOutHandler) {
        await opts.forceSignOutHandler.forceSignOut(req);
      }
      res.status(200).send();
    });
  }