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
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-31 16:00 +0000
1import re
3from sqlalchemy import Column, text, ForeignKey
4from sqlalchemy.dialects import mysql
5from sqlalchemy.orm import relationship
7from rfpy.model.meta import Base
10class Category(Base):
12 __tablename__ = 'categories'
13 __table_args__ = (
14 {'mysql_engine': "InnoDB", 'mysql_charset': 'utf8mb4'},
15 )
17 public_attrs = ['id', 'name', 'description']
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 )
28 organisation = relationship('Organisation', backref='categories')
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)
37 def __repr__(self):
38 return '(%s) %s' % (self.org_id, self.name)
41def clean_search_term(term):
42 if len(term) > 100:
43 raise ValueError('search term cannot be longer than 100 characters')
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
55 token = token.lstrip('*')
56 token = token.rstrip('-+~')
58 cleaned.append(token)
60 return ' '.join(cleaned)