Coverage for rfpy/model/misc.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-31 16:00 +0000

1import re 

2 

3from sqlalchemy import Column, text, ForeignKey 

4from sqlalchemy.dialects import mysql 

5from sqlalchemy.orm import relationship 

6 

7from rfpy.model.meta import Base 

8 

9 

10class Category(Base): 

11 

12 __tablename__ = 'categories' 

13 __table_args__ = ( 

14 {'mysql_engine': "InnoDB", 'mysql_charset': 'utf8mb4'}, 

15 ) 

16 

17 public_attrs = ['id', 'name', 'description'] 

18 

19 name = Column(mysql.VARCHAR(50), nullable=False, server_default=text("''")) 

20 description = Column(mysql.VARCHAR(255), nullable=False, server_default=text("''")) 

21 org_id = Column( 

22 mysql.VARCHAR(150), 

23 ForeignKey('organisations.id', ondelete='CASCADE', onupdate='CASCADE'), 

24 nullable=False, 

25 server_default=text("''") 

26 ) 

27 

28 organisation = relationship('Organisation', backref='categories') 

29 

30 # TODO - does this expose security hole enabling org A to 

31 # get a category and lookup projects for org B? 

32 projects = relationship('Project', 

33 secondary='project_categories', 

34 lazy='dynamic', 

35 viewonly=True) 

36 

37 def __repr__(self): 

38 return '(%s) %s' % (self.org_id, self.name) 

39 

40 

41def clean_search_term(term): 

42 if len(term) > 100: 

43 raise ValueError('search term cannot be longer than 100 characters') 

44 

45 cleaned = [] 

46 tokens = term.split() 

47 for token in tokens: 

48 try: 

49 word = re.match(r'\W*(\w+)', token).groups()[0] 

50 if len(word) < 3: 

51 continue 

52 except Exception: 

53 continue 

54 

55 token = token.lstrip('*') 

56 token = token.rstrip('-+~') 

57 

58 cleaned.append(token) 

59 

60 return ' '.join(cleaned)