class Client(BaseModel): """ Clients are client endpoints. Access is determined by group membership. """ __tablename__ = 'client' client_id = db.Column(db.Integer, unique=True) name = db.Column(db.String(32), unique=True, nullable=False) description = db.Column(db.String(500), nullable=True) # Relationships groups = db.relationship('Group', secondary=group_client, lazy='subquery', backref=db.backref('clients', lazy=True)) def __repr__(self): return (f"Client('{self.name}')") def add_group(self, group): """ Add a group that has permissions for the client. """ if group not in self.groups: self.groups.append(group) def rm_group(self, group): """ Remove a group that no longer has permissions for the client. """ try: self.groups.remove(group) except ValueError: pass
class Role(db.Model): """ Roles for granting granular access to users. """ __tablename__ = 'roles' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(50), unique=True)
class Group(BaseModel): """ Basic user groups. """ __tablename__ = 'group' name = db.Column(db.String(100), unique=True, nullable=False) description = db.Column(db.String(500), nullable=True) # Relationships users = db.relationship('User', secondary=user_group, lazy='subquery', backref=db.backref('groups', lazy=True)) def __repr__(self): return(f"Group('{self.name}')") def add_user(self, user): """ Add a user to the group. """ if user not in self.users: self.users.append(user) def rm_user(self, user): """ remove a user from the group. """ try: self.users.remove(user) except ValueError: pass
class Notification(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), index=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) timestamp = db.Column(db.Float(precision=15), index=True, default=time) payload_json = db.Column(db.Text) def get_data(self): return json.loads(str(self.payload_json))
class WildapricotGroup(BaseModel): """ Group information pulled from Wildapricot """ __tablename__ = 'wildapricot_group' wildapricot_group_id = db.Column(db.Integer, nullable=True) mcp_group_id = db.Column(db.Integer, db.ForeignKey('group.id'), nullable=True)
class BaseModel(db.Model): """ A base for all database models to implement common requirements. """ __abstract__ = True id = db.Column(db.Integer, primary_key=True) created_date = db.Column(db.DateTime, default=db.func.current_timestamp()) modified_date = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp())
class WildapricotUser(BaseModel): """ User information pulled from Wildapricot """ __tablename__ = 'wildapricot_user' wildapricot_user_id = db.Column(db.Integer, nullable=True) mcp_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True) last_sync_time = db.Column(db.DateTime, nullable=True) def url(self): sub = settings.get('wildapricot', 'subdomain') url = f"https://{sub}.wildapricot.org/admin/contacts/details/?contactId={self.wildapricot_user_id}" return url
class Task(db.Model): id = db.Column(db.String(36), primary_key=True) name = db.Column(db.String(128), index=True) description = db.Column(db.String(128)) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) complete = db.Column(db.Boolean, default=False) def get_rq_job(self): try: rq_job = rq.job.Job.fetch(self.id, connection=current_app.redis) except (redis.exceptions.RedisError, rq.exceptions.NoSuchJobError): return None return rq_job def get_progress(self): job = self.get_rq_job() return job.meta.get('progress', 0) if job is not None else 100
class Log(BaseModel): """ Basic log template. """ log_level = db.Column(db.Enum(LogLevel), nullable=False) log_type = db.Column(db.String(20), nullable=False) event_type = db.Column(db.String(20), nullable=False) source_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True) target_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True) details = db.Column(db.String(1024), nullable=True) key_id = db.Column(db.String(20), nullable=True) # action = db.Column() def __repr__(self): return (f"Log('{self.log_type}')")
class User(BaseModel, UserMixin): """ Basic user for login and information tracking. """ __tablename__ = 'user' username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) email_confirmed_at = db.Column(db.DateTime()) first_name = db.Column(db.String(30), server_default='') last_name = db.Column(db.String(30), server_default='') birthdate = db.Column(db.Date, nullable=True, default=None) image_file = db.Column(db.String(20), nullable=False, default='default.jpg') password = db.Column(db.String(60), nullable=False, server_default='') nfc_id = db.Column(db.String(20), nullable=True, default=None, unique=True) join_date = db.Column(db.DateTime, nullable=True, default=datetime.utcnow) background_check_date = db.Column(db.DateTime, nullable=True) last_seen = db.Column(db.DateTime) active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1') updated_date = db.Column(db.DateTime, default=datetime.utcnow) # Relationships roles = db.relationship('Role', secondary='user_roles') notifications = db.relationship('Notification', backref='user', lazy='dynamic') tasks = db.relationship('Task', backref='user', lazy='dynamic') def __eq__(self, user2): if not isinstance(user2, User): # don't attempt to compare against unrelated types return NotImplemented for item in self.__dict__: if item == '_sa_instance_state': continue try: if getattr(self, item) != getattr(user2, item): # print(f"{item} : {getattr(self, item)} : {getattr(user2, item)} ") return False except AttributeError: return False return True def set_updated_date(self): self.updated_date = datetime.utcnow() def set_password(self, password): hashed_password = bcrypt.generate_password_hash(password) \ .decode('utf-8') self.password = hashed_password # db.session.commit() def check_password(self, password): match = bcrypt.check_password_hash(self.password, password) return match def get_reset_token(self, expires_sec=1800): s = Serializer(current_app.config['SECRET_KEY'], expires_sec) return s.dumps({'user_id': self.id}).decode('utf-8') def get_role_names(self): return [role.name for role in self.roles] @staticmethod def verify_reset_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: user_id = s.loads(token)['user_id'] except Exception: return None return User.query.get(user_id) def add_notification(self, name, data): self.notifications.filter_by(name=name).delete() n = Notification(name=name, payload_json=json.dumps(data), user=self) db.session.add(n) return n def launch_task(self, name, description, timeout, *args, **kwargs): rq_job = current_app.task_queue.enqueue(name, job_timeout=timeout, *args, **kwargs) task = Task(id=rq_job.get_id(), name=name, description=description, user=self) db.session.add(task) return task def get_tasks_in_progress(self): return Task.query.filter_by(user=self, complete=False).all() def get_task_in_progress(self, name): return Task.query.filter_by(name=name, user=self, complete=False).first() # Group functions def add_group(self, group): """ Add the user to a group. """ if group not in self.groups: self.groups.append(group) self.set_updated_date() def rm_group(self, group): """ remove the user from a group. """ try: self.groups.remove(group) self.set_updated_date() except ValueError: pass def set_groups(self, groups): """ set the user's groups. """ if not self.groups == groups: self.groups = groups self.set_updated_date() def __repr__(self): return (f"User('{self.username}', '{self.email}', " f"'{self.image_file}', '{self.join_date}')")
def get_data(self): return json.loads(str(self.payload_json)) class Role(db.Model): """ Roles for granting granular access to users. """ __tablename__ = 'roles' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(50), unique=True) users_roles = db.Table( 'user_roles', db.Column('user_id', db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE')), db.Column('role_id', db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE')), ) # class UserRoles(db.Model): # """ # Links users to their roles. # """ # __tablename__ = 'user_roles' # __table_args__ = {'extend_existing': True} # id = db.Column(db.Integer(), primary_key=True) # user_id = db.Column(db.Integer(), db.ForeignKey('user.id', # ondelete='CASCADE')) # role_id = db.Column(db.Integer(), db.ForeignKey('roles.id',
from flask import current_app from mcp import db from mcp.main.models import BaseModel group_client = db.Table('group_client', db.Column('client_id', db.Integer, db.ForeignKey('client.id'), primary_key=True), db.Column('group_id', db.Integer, db.ForeignKey('group.id'), primary_key=True), extend_existing=True) class Client(BaseModel): """ Clients are client endpoints. Access is determined by group membership. """ __tablename__ = 'client' client_id = db.Column(db.Integer, unique=True) name = db.Column(db.String(32), unique=True, nullable=False) description = db.Column(db.String(500), nullable=True) # Relationships groups = db.relationship('Group', secondary=group_client, lazy='subquery',
from datetime import datetime from flask import current_app from mcp import db, ma from mcp.main.models import BaseModel user_group = db.Table( 'user_group', db.Column('group_id', db.Integer, db.ForeignKey('group.id'), primary_key=True), db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True), extend_existing=True ) class Group(BaseModel): """ Basic user groups. """ __tablename__ = 'group' name = db.Column(db.String(100), unique=True, nullable=False) description = db.Column(db.String(500), nullable=True) # Relationships users = db.relationship('User', secondary=user_group, lazy='subquery', backref=db.backref('groups', lazy=True)) def __repr__(self): return(f"Group('{self.name}')")