Example #1
0
    def test_DuplicateTagsAreNotIndexed(self):
        user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
        tag1 = 'asdf'
        tag2 = 'qwer'
        tag3 = 'uiop'
        recipe1 = Models.Recipe(
            name='test recipe',
            description='hello world, goodbye mars',
            private=False,
            owner=user.id,
            tags=[tag1],
        ).save()

        recipe2 = Models.Recipe(
            name='test recipe',
            description='hello world, goodbye mars',
            private=False,
            owner=user.id,
            tags=[tag1, tag2],
        ).save()

        recipe3 = Models.Recipe(
            name='test recipe',
            description='hello world, goodbye mars',
            private=False,
            owner=user.id,
            tags=[tag2, tag3],
        ).save()

        UserTagsApi.UserTagsApi.indexRecipeTags(recipe1)
        UserTagsApi.UserTagsApi.indexRecipeTags(recipe2)
        UserTagsApi.UserTagsApi.indexRecipeTags(recipe3)

        userTags = UserTagsApi.UserTagsApi.getTagsForUser(user.id)
        self.assertEquals(sorted([tag1, tag2, tag3]), sorted(userTags.tags))
Example #2
0
 def _parseStepsFromScraper(cls, scraper) -> [Models.RecipeStep]:
     rcpSteps = []
     step: str
     for step in scraper.instructions().split('\n'):
         stepLen = Models.RecipeStepLength(
             time=0,
             unit='m'
         )
         potentialLenMatches = re.search(cls.lenPattern, step.strip(), re.IGNORECASE)
         if potentialLenMatches is not None:
             foundMatches = potentialLenMatches.groups()
             if len(foundMatches) >= 2:
                 timeUnit = None
                 rawUnit = foundMatches[1].lower()
                 if rawUnit.find('minute') != -1:
                     timeUnit = 'm'
                 elif rawUnit.find('hour') != -1:
                     timeUnit = 'h'
                 elif rawUnit.find('second') != -1:
                     timeUnit = 's'
                 elif rawUnit.find('week') != -1:
                     timeUnit = 'w'
                 elif rawUnit.find('day') != -1:
                     timeUnit = 'd'
                 if timeUnit is not None:
                     stepLen = Models.RecipeStepLength(
                         time=int(foundMatches[0]),
                         unit=timeUnit,
                     )
         rcpSteps.append(Models.RecipeStep(
             content=step.strip(),
             length=stepLen,
         ))
     return rcpSteps
Example #3
0
    def test_TagsAreUpdatedOnUpdate(self):
        user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
        UserTagsApi.UserTagsApi.createDefaultUserTags(user.id)
        recipe = Models.Recipe(
            owner=user.id,
            name='test tags recipe',
            description='asdfqwer',
            private=False,
            sections=[
                Models.RecipeSection(
                    name='s1',
                    steps=[Models.RecipeStep(content='asdfqwer')],
                    ingredients=[
                        Models.RecipeIngredient(name='asdf', amount='qwer')
                    ])
            ],
            tags=['asdf', 'qwer'])
        # save the recipe
        recipe = RecipeApi.RecipeApi.createRecipe(recipe.toJson(), user.id)
        recipe.tags = ['zxcv', 'uiop']
        RecipeApi.RecipeApi.updateRecipe(recipe.toJson(), recipe)

        # check there are now tags
        userTags = UserTagsApi.UserTagsApi.getAllTagsForUser(user.id)
        self.assertEquals(1, len(userTags))
        # all the tags should be present
        self.assertEquals(['asdf', 'qwer', 'zxcv', 'uiop'].sort(),
                          userTags[0].tags.sort())
Example #4
0
 def test_ConvertIngredientInDifferentCategoryBase(self):
     ing = Models.RecipeIngredient(name='Flour', amount='1 1/2', unit='c')
     # convert to grams
     converted = RecipeOperations.RecipeOperations.convertIngredientToUnit(
         ing, 'g')
     convertedAmount = Utilities.convert_to_float(converted.amount)
     self.assertAlmostEqual(180, round(convertedAmount))
Example #5
0
    def _parseIngsFromScraper(cls, scraper) -> [Models.RecipeIngredient]:
        rcpIngs = []
        parser = ingreedypy.Ingreedy()

        for ingredient in scraper.ingredients():
            ingToParse = ingredient.lower()
            ingToParse = cls._stripAndedFractions(ingToParse)
            parsedIngredient = parser.parse(ingToParse)

            ing = ingToParse
            amount = ''
            unit = None
            if parsedIngredient.get('ingredient', None) is not None:
                ing = parsedIngredient['ingredient']
                if len(parsedIngredient.get('quantity', [])) > 0:
                    quantity = parsedIngredient['quantity'][0]
                    amount = quantity.get('amount', '')
                    unit = quantity.get('unit', None)

            rcpIngs.append(Models.RecipeIngredient(
                name=ing,
                amount=str(amount),
                unit=unit,
            ))
        return rcpIngs
Example #6
0
 def createShoppingList(cls, entity: dict,
                        userId: str) -> Models.ShoppingList:
     entity['owner'] = userId
     shoppingList = Models.ShoppingList(**entity)
     shoppingList.save()
     UserCountsApi.UserCountsApi.incrementShoppingLists(1, userId)
     return shoppingList
Example #7
0
 def test_GetForUserWithPrivateRecipes(self):
     user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
     for i in range(0, DatabaseConstants.PAGE_SIZE):
         sectionId = str(uuid.uuid4())
         RecipeApi.RecipeApi.createRecipe(
             dict(
                 name=f'Test Recipe {i}',
                 description=f'Test Des {i}',
                 owner=user.id,
                 private=i % 2 == 0,
                 sections=[
                     dict(id=sectionId,
                          name='Test Section',
                          ingredients=[
                              dict(
                                  name=f'ing {i}',
                                  amount='100',
                                  unit='grams',
                              )
                          ],
                          steps=[
                              dict(
                                  content='asdf' * 20,
                                  length=Models.RecipeStepLength(time=1,
                                                                 unit='m'),
                              )
                          ])
                 ],
             ), user.id)
     firstPage = RecipeApi.RecipeApi.listForUser(user.id,
                                                 0,
                                                 None,
                                                 allowPrivate=False)
     self.assertEqual(int(DatabaseConstants.PAGE_SIZE / 2),
                      len(firstPage.data))
Example #8
0
 def test_ConvertIngredientInDifferentCategoryUnit(self):
     ing = Models.RecipeIngredient(name='Flour', amount='10', unit='tbsps')
     # convert to ounces
     converted = RecipeOperations.RecipeOperations.convertIngredientToUnit(
         ing, 'oz')
     convertedAmount = Utilities.convert_to_float(converted.amount)
     self.assertAlmostEqual(2.65, round(convertedAmount, 2))
Example #9
0
 def _createShoppingList(self) -> (Models.User, Models.ShoppingList):
     user = UserApi.UserApi.create('*****@*****.**',
                                   'asdfqwer')
     shoppingList = Models.ShoppingList(owner=user.id,
                                        created=int(time.time()),
                                        listItems=[
                                            Models.ShoppingListItem(
                                                name='Test Item',
                                                notes='Test Notes',
                                                ordinal=0,
                                                completed=False)
                                        ],
                                        name='Test List',
                                        allowed=[])
     return user, ShoppingListApi.ShoppingListApi.createShoppingList(
         shoppingList.toJson(), user.id)
Example #10
0
 def test_ConvertIngredientInSameCategory(self):
     ing = Models.RecipeIngredient(name='Test Ingredient',
                                   amount='1 1/2',
                                   unit='cups')
     # convert to tbsp
     converted = RecipeOperations.RecipeOperations.convertIngredientToUnit(
         ing, 'tbsp')
     convertedAmount = Utilities.convert_to_float(converted.amount)
     self.assertAlmostEqual(24, round(convertedAmount))
Example #11
0
 def createRecipeBook(cls, entity: dict, userId: str) -> Models.RecipeBook:
     userCounts = UserCountsApi.UserCountsApi.getForUser(userId)
     if not PermissionsApi.PermissionsApi.hasProTierPermission(
             userId) and userCounts.recipeBooks >= 10:
         raise ApiExceptions.PaymentRequiredException
     entity['owner'] = userId
     createdEntity = Models.RecipeBook(**entity)
     createdEntity.save()
     UserCountsApi.UserCountsApi.incrementRecipeBooks(1, userId)
     return createdEntity
Example #12
0
 def createRecipeBooks(cls, num: int, user: Models.User) -> List[Models.RecipeBook]:
     books = []
     for i in range(0, num):
         recipeBook = RecipeBookApi.RecipeBookApi.createRecipeBook(Models.RecipeBook(
             owner=str(user.id),
             name=f'Recipe Book {i}',
             description=lorem.paragraph(),
             recipes=[],
         ).toJson(), str(user.id))
         books.append(recipeBook)
     return books
Example #13
0
 def deserializeSession(cls, token: str) -> Models.Session:
     decodedSession = base64.b64decode(token.encode('utf-8')).decode('utf-8')
     parts = decodedSession.split('.')
     if len(parts) == 3:
         parts.append('login')
     # noinspection PyTypeChecker
     return Models.Session(
         id=parts[0],
         owner=parts[1],
         created=int(parts[2]),
         sessionType=parts[3],
     )
Example #14
0
    def testGrantAccessToOtherUser(self):
        ownerUser, shoppingList = self._createShoppingList()
        sharingUserEmail = '*****@*****.**'
        sharingUser = UserApi.UserApi.create(sharingUserEmail, 'asdfqwer')
        shoppingList = ShoppingListApi.ShoppingListApi.grantUserAccess(
            shoppingList, sharingUserEmail, ownerUser.id)

        self.assertEquals(1, len(shoppingList.allowed))
        self.assertEquals(
            Models.AllowedListUser(userId=sharingUser.id,
                                   username=sharingUser.email),
            shoppingList.allowed[0])
Example #15
0
 def requestForgottenPasswordReset(cls, email: str) -> str:
     user = UserApi.UserApi.getByUsername(email)
     if user is None:
         raise ApiExceptions.NotFoundException
     forgottenPasswordToken = Models.ForgotPasswordToken(
         token=str(uuid.uuid4()),
         owner=user.id,
         created=int(time.time())
     )
     forgottenPasswordToken.save()
     EmailSender.EmailSender.sendForgotPasswordEmail(user.email, forgottenPasswordToken.token)
     return forgottenPasswordToken.token
Example #16
0
 def _createRecipe(self) -> (Models.User, Models.Recipe):
     user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
     recipeBody = Models.Recipe(
         name='Test Recipe',
         description='A really cool recipe that we can test with',
         owner=user.id,
         private=False,
         sections=[
             Models.RecipeSection(
                 name='test-section',
                 id=Models.DEFAULT_SECTION_ID,
                 steps=[
                     Models.RecipeStep(content='asdfqwer',
                                       length=Models.RecipeStepLength(
                                           time=10, unit='m')),
                     Models.RecipeStep(content='zxcvbnm,',
                                       length=Models.RecipeStepLength(
                                           time=1, unit='d')),
                 ],
                 ingredients=[
                     Models.RecipeIngredient(name='milk',
                                             amount='1/2',
                                             unit='cup'),
                     Models.RecipeIngredient(name='egg', amount='3'),
                     Models.RecipeIngredient(name='water',
                                             amount='150',
                                             unit='ml')
                 ],
             )
         ],
         tags=[],
         advanced=Models.RecipeAdvancedOptions())
     recipe = RecipeApi.RecipeApi.createRecipe(recipeBody.toJson(), user.id)
     self.assertEqual('Test Recipe', recipe.name)
     self.assertEqual('A really cool recipe that we can test with',
                      recipe.description)
     self.assertEqual(2, len(recipe.sections[0].steps))
     self.assertEqual(3, len(recipe.sections[0].ingredients))
     return user, recipe
Example #17
0
 def parseScraperIntoRecipe(cls, url: str, userId: str) -> Models.Recipe:
     scraper = recipe_scrapers.scrape_me(url, wild_mode=True)
     return Models.Recipe(
         name=scraper.title(),
         description=cls._parseDescriptionFromScraper(url, scraper),
         private=False,
         created=int(time.time()),
         owner=userId,
         advanced=Models.RecipeAdvancedOptions(
             highAltitude=False,
             altitude=0
         ),
         tags=[],
         sections=[
             Models.RecipeSection(
                 id=Models.DEFAULT_SECTION_ID,
                 ingredients=cls._parseIngsFromScraper(scraper),
                 steps=cls._parseStepsFromScraper(scraper),
                 name=scraper.title()
             )
         ],
     )
Example #18
0
 def test_UpdateRecipe(self):
     _, recipe = self._createRecipe()
     recipe.name = 'A new name'
     recipe.sections[0].ingredients.append(
         Models.RecipeIngredient(name='A new ingredient',
                                 amount='1.25',
                                 unit='T'))
     recipe.sections[0].steps = recipe.sections[0].steps[0:2]
     updatedRecipe = RecipeApi.RecipeApi.updateRecipe(
         recipe.toJson(), recipe)
     self.assertEqual(4, len(updatedRecipe.sections[0].ingredients))
     self.assertEqual(2, len(updatedRecipe.sections[0].steps))
     self.assertIsNotNone(updatedRecipe.id)
     self.assertEqual(recipe.name, updatedRecipe.name)
Example #19
0
    def test_IndexRecipeWithUniqueTags(self):
        user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
        recipe = Models.Recipe(
            name='test recipe',
            description='hello world, goodbye mars',
            private=False,
            owner=user.id,
            tags=['asdf', 'qwer'],
        ).save()

        UserTagsApi.UserTagsApi.indexRecipeTags(recipe)

        userTags = UserTagsApi.UserTagsApi.getTagsForUser(user.id)
        self.assertEquals(sorted(userTags.tags), sorted(recipe.tags))
Example #20
0
    def test_DeleteUser(self):
        user = self._createUser()
        createdId = user.id

        sessions = []
        recipes = []
        books = []
        for i in range(0, 20):
            sessions.append(SessionApi.SessionApi.createSessionForUser(
                user.id))
            recipes.append(
                RecipeApi.RecipeApi.createRecipe(
                    Models.Recipe(
                        name=f'Recipe {i}',
                        description=f'Recipe number {i}',
                        sections=[
                            Models.RecipeSection(
                                id=str(uuid.uuid4()),
                                name='test-section',
                                ingredients=[
                                    Models.RecipeIngredient(
                                        name=f'test ing {i}',
                                        amount=str(i),
                                    )
                                ],
                                steps=[
                                    Models.RecipeStep(
                                        content='asdfqwer',
                                        length=Models.RecipeStepLength())
                                ],
                            )
                        ],
                        private=False,
                        owner=createdId).toJson(), createdId))
            books.append(
                RecipeBookApi.RecipeBookApi.createRecipeBook(
                    Models.RecipeBook(recipes=[],
                                      description=f'Test book {i} asdfqwer',
                                      name=f'Test Book {i}',
                                      owner=user.id).toJson(), createdId))

        # delete the user
        thread = UserApi.UserApi.delete(createdId)
        thread.join()

        # try to get the user -- it shouldn't be there
        fetchedUser = UserApi.UserApi.getById(createdId)
        self.assertIsNone(fetchedUser)

        # there should be no sessions
        self.assertEquals(0, len(list(Models.Session.getByOwner(user.id))))
        # there should be no recipes
        self.assertEquals(0, len(list(Models.Recipe.getByOwner(user.id))))
        # there should be no recipe books
        self.assertEquals(0, len(list(Models.RecipeBook.getByOwner(user.id))))
        # there should be no user tags
        self.assertEquals(0, len(list(Models.UserTags.getByOwner(user.id))))
Example #21
0
 def create(cls,
            username: str,
            password: str,
            createDefaults=True) -> Models.User:
     # expecting an email and password here, but we need to salt/hash the password
     passwordHash, salt, nonce = Encryption.encryptPassword(password)
     user = Models.User(email=username,
                        password=passwordHash,
                        salt=salt,
                        nonce=nonce,
                        created=int(time.time()),
                        preferences={},
                        permissions=[],
                        subscriptionId=None)
     user.save()
     if createDefaults:
         cls._createDefaults(user.id)
     return user
Example #22
0
 def stageUser(cls, email: str, password: str) -> Models.StagedUser:
     passwordHash, salt, nonce = Encryption.encryptPassword(password)
     stagedUser = Models.StagedUser(email=email,
                                    password=passwordHash,
                                    salt=salt,
                                    nonce=nonce,
                                    created=int(time.time()),
                                    token=str(uuid.uuid4()))
     try:
         stagedUser.save()
     except pymongo.errors.DuplicateKeyError:
         raise ApiExceptions.ConflictException()
     # check that this name doesn't clash with another user
     matchingUser = cls.getByUsername(email)
     if matchingUser is not None:
         raise ApiExceptions.ConflictException()
     EmailSender.EmailSender.sendConfirmSignupToken(email, stagedUser.token)
     return stagedUser
Example #23
0
 def createFromStagedUser(cls, token: str) -> Models.User:
     stagedUser: Models.StagedUser = next(
         Models.StagedUser.query({'token': token}))
     if stagedUser is None:
         raise ApiExceptions.NotFoundException
     user = Models.User(email=stagedUser.email,
                        password=stagedUser.password,
                        salt=stagedUser.salt,
                        nonce=stagedUser.nonce,
                        created=int(time.time()),
                        preferences={},
                        permissions=[],
                        subscriptionId=None)
     # create the user entity
     user.save()
     cls._createDefaults(user.id)
     # destroy the staged user
     stagedUser.delete()
     return user
Example #24
0
    def createRecipes(cls, num: int, user: Models.User, books: List[Models.RecipeBook]) -> List[Models.Recipe]:
        ingNames = CommonIngredientApi.CommonIngredientApi.getCommonIngredientNames()
        measureNames = list(map(lambda km: km.name.p, RecipeApi.RecipeApi.getKnownMeasures()))
        recipes = []
        for i in range(0, num):
            sections = []
            for sectionNum in range(0, random.randint(1, 6)):
                steps = []
                for _ in range(0, random.randint(1, 20)):
                    steps.append(Models.RecipeStep(
                        content=lorem.paragraph(),
                        length=Models.RecipeStepLength(
                            time=random.randint(0, 60),
                            unit='m'
                        )
                    ))
                ingredients = []
                for _ in range(0, random.randint(1, 10)):
                    ingredients.append(Models.RecipeIngredient(
                        name=random.choice(ingNames),
                        amount=str(random.random() * 100),
                        unit=random.choice(measureNames)
                    ))
                sections.append(Models.RecipeSection(
                    name=f'Test Section {sectionNum}',
                    steps=steps,
                    ingredients=ingredients,
                    id=str(uuid.uuid4())
                ))

            recipe = RecipeApi.RecipeApi.createRecipe(Models.Recipe(
                name=f'Test Recipe {i}',
                description=lorem.paragraph(),
                private=random.randint(0, 100) % 2 == 0,
                advanced=Models.RecipeAdvancedOptions(),
                sections=sections,
                tags=[],
                owner=str(user.id)
            ).toJson(), str(user.id))
            recipes.append(recipe)

            addToBook = random.randint(0, 100) % 2 == 0
            if addToBook:
                recipeBook = random.choice(books)
                recipeBook.recipes.append(recipe.id)

        for recipeBook in books:
            recipeBook.save()

        return recipes
Example #25
0
    def createRecipe(cls, entity: dict, userId: str) -> Models.Recipe:
        for section in entity['sections']:
            if len(section.get('steps', [])) == 0 or len(
                    section.get('ingredients', [])) == 0:
                raise ApiExceptions.BadRequestException

        userCounts = UserCountsApi.UserCountsApi.getForUser(userId)
        user = Models.User.getById(userId)
        if not PermissionsApi.PermissionsApi.hasProTierPermission(
                user.id) and userCounts.recipes >= 50:
            raise ApiExceptions.PaymentRequiredException

        createdEntity = Models.Recipe(**entity)
        createdEntity.owner = userId
        createdEntity.save()
        # index the tags on this recipe
        TaskRunner.TaskRunner.runTask(RecipeTasks.RecipeTasks.indexRecipeTags,
                                      createdEntity)
        UserCountsApi.UserCountsApi.incrementRecipes(1, userId)
        return createdEntity
Example #26
0
 def loginUser(cls, username: str, password: str) -> (str, Models.User):
     userLookup = cls.getByUsername(username)
     if userLookup is not None:
         expectedPassword = userLookup.password
         expectedSalt = userLookup.salt
         expectedNonce = userLookup.nonce
         if Encryption.comparePasswords(expectedPassword, expectedNonce,
                                        expectedSalt, password):
             # generate a session for the user
             session = Models.Session(
                 owner=userLookup.id,
                 created=int(time.time()),
                 sessionType='login',
             )
             session.save()
             return SessionApi.SessionApi.serializeSession(
                 session), userLookup
         else:
             raise ApiExceptions.ForbiddenException()
     else:
         raise ApiExceptions.NotFoundException()
Example #27
0
 def grantUserAccess(cls, shoppingList: Models.ShoppingList,
                     emailAddress: str,
                     requestingId: str) -> Models.ShoppingList:
     if requestingId != shoppingList.owner:
         raise ApiExceptions.ForbiddenException
     userToAdd = UserApi.UserApi.getByUsername(emailAddress)
     if userToAdd is None:
         raise ApiExceptions.NotFoundException
     allowedUsers = shoppingList.allowed or []
     allowedUser: Models.AllowedListUser
     mappedIds = [allowedUser.userId for allowedUser in allowedUsers]
     if userToAdd.id not in mappedIds:
         allowedUser = Models.AllowedListUser(userId=userToAdd.id,
                                              username=userToAdd.email)
         allowedUsers.append(allowedUser)
         shoppingList.allowed = allowedUsers
         shoppingList.save()
         owner = Models.User.getById(shoppingList.owner)
         EmailSender.EmailSender.sendSharedShoppingList(
             emailAddress, owner.email, shoppingList.id)
         return shoppingList
     return shoppingList
Example #28
0
    def test_QueryIngredient(self):
        ingredientName = 'Query Ingredient'
        user, recipe = self._createRecipe()
        recipe.sections[0].ingredients.append(
            Models.RecipeIngredient(name=ingredientName,
                                    unit='cups',
                                    amount='1 1/2'))
        recipe = RecipeApi.RecipeApi.updateRecipe(recipe.toJson(), recipe)
        recipes = RecipeApi.RecipeApi.listForUser(
            user.id, 0, {'ingredients': [ingredientName]}, allowPrivate=True)
        self.assertEquals(1, len(recipes.data))
        self.assertEquals(recipe.id, str(recipes.data[0].id))

        recipes = RecipeApi.RecipeApi.listForUser(
            user.id, 0, {'ingredients': ['unknown name']}, allowPrivate=True)
        self.assertEquals(0, len(recipes.data))

        recipes = RecipeApi.RecipeApi.listForUser(
            user.id,
            0, {'ingredients': ['unknown name',
                                ingredientName.upper()]},
            allowPrivate=True)
        self.assertEquals(1, len(recipes.data))
Example #29
0
    def test_PrunedTagsAreNotIndexed(self):
        user = UserApi.UserApi.create('*****@*****.**', 'asdfqwer')
        userTags = UserTagsApi.UserTagsApi.getTagsForUser(user.id)

        tagToPrune = 'uiop'

        userTags.pruned = [tagToPrune]
        userTags.save()

        # try to index a recipe with uiop as the tag
        recipe = Models.Recipe(
            name='test recipe',
            description='hello world, goodbye mars',
            private=False,
            owner=user.id,
            tags=['asdf', 'qwer', tagToPrune],
        ).save()
        updatedTags = UserTagsApi.UserTagsApi.indexRecipeTags(recipe)

        self.assertIn('asdf', updatedTags.tags)
        self.assertIn('qwer', updatedTags.tags)
        self.assertNotIn(tagToPrune, updatedTags.tags)
        self.assertIn(tagToPrune, updatedTags.pruned)
Example #30
0
 def createDefaultUserCounts(cls, userId: str) -> Models.UserCounts:
     model = Models.UserCounts(owner=userId,
                               recipes=0,
                               recipeBooks=0,
                               shoppingLists=0)
     return model.save()