class Voucher(db.Model): id = db.Column(db.Integer, primary_key=True) batchid = db.Column(db.String(40), index=True) voucher = db.Column(db.String(20), index=True) notes = db.Column(db.String(50), index=True) duration_t = db.Column(db.BigInteger(), default=3600) bytes_t = db.Column(db.BigInteger(), default=1000) speed_dl = db.Column(db.BigInteger(), default=256) speed_ul = db.Column(db.BigInteger(), default=256) used = db.Column(db.Boolean(), default=False, index=True) num_devices = db.Column(db.Integer, default=1, index=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) duration = db.Column(db.String(20), index=True, default='1 Hours') used_at = db.Column( db.DateTime, index=True) #used time in UTC,filled once voucher is used device_id = db.Column(db.Integer, db.ForeignKey('device.id')) sessions = db.relationship('Guestsession', backref='voucher', lazy='dynamic') #to track sessions devices = db.relationship("Device", secondary=vouchers_devices, backref="vouchers") def populate_from_form(self, form): self.notes = form.notes.data self.bytes_t = form.bytes_t.data self.num_devices = form.num_devices.data self.speed_ul = form.speed_ul.data self.speed_dl = form.speed_dl.data #set duration accordingly if form.duration_t.data == 1: self.duration = form.duration.data + ' Hours' self.duration_t = int(form.duration.data) * 60 * 60 elif form.duration_t.data == 2: self.duration = form.duration.data + ' Days' self.duration_t = int(form.duration.data) * 60 * 60 * 24 elif form.duration_t.data == 3: self.duration = form.duration.data + ' Months' self.duration_t = int(form.duration.data) * 60 * 60 * 24 * 30 def to_dict(self): return { 'site': self.site.name, 'duration': self.duration, 'status': '<span class="label label-danger">Used</span>' if self.used else '<span class="label label-success">Initializing</span>', 'voucher': self.voucher, 'note': self.notes, 'bytes_t': self.bytes_t, 'num_devices': self.num_devices, 'id': self.id } #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = Voucher.query.filter_by(site_id=modal_filters['siteid']) if term: result_qry = main_query.outerjoin(Voucher.site).filter( or_(Wifisite.name.like('%' + term + '%'), Voucher.voucher.like('%' + term + '%'), Voucher.notes.like('%' + term + '%'))) else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(Wifisite.name.desc()) else: results_ord = result_qry.order_by(Wifisite.name.asc()) elif sort['column'] == "1": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.voucher.desc()) else: results_ord = result_qry.order_by(Voucher.voucher.desc()) elif sort['column'] == "2": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.duration.desc()) else: results_ord = result_qry.order_by(Voucher.duration.desc()) elif sort['column'] == "3": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.used.desc()) else: results_ord = result_qry.order_by(Voucher.used.desc()) elif sort['column'] == "4": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.notes.desc()) else: results_ord = result_qry.order_by(Voucher.notes.desc()) else: results_ord = result_qry.order_by(Voucher.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results} def to_table_row(self): duration = '%s:%sMb ' % (self.duration, self.bytes_t) return { 'site': self.site.name, 'duration': duration, 'status': '<span class="label label-danger">Used</span>' if self.used else '<span class="label label-primary">Available</span>', 'voucher': self.voucher, 'note': self.notes, 'num_devices': self.num_devices, 'used': self.used, 'id': self.id } def check_validity(self): #first check if voucher is already used and #first check if voucher's expiry time is over now = arrow.utcnow().timestamp expiry = arrow.get(self.used_at).timestamp + self.duration_t if now >= expiry: return False #check if data limit us expired if self.bytes_t: data_consumed = 0 for session in self.sessions: data_consumed += int(session.data_used) data_mb = int(math.ceil((data_consumed / 1024000.0))) if data_mb > self.bytes_t: return False return True def time_available(self): '''Retuns remaining time in a voucher in minutes ''' now = arrow.utcnow().timestamp expiry = arrow.get(self.used_at).timestamp + self.duration_t return int((expiry - now) / 60) def data_available(self): '''Retuns remaining data in a voucher in Mb ''' if self.bytes_t: data_consumed = 0 for session in self.sessions: data_consumed += int(session.data_used) data_mb = int(math.ceil((data_consumed / 1024000.0))) return self.bytes_t - data_mb else: return 0 def uses_available(self): '''Retuns number of uses available in this voucher ''' free = int(self.num_devices) - len(self.devices) return free
class Client(User): ''' Class to represent admin, each admin will be associated with a user of type admin ''' id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) sites = db.relationship('Wifisite', backref='client', lazy='dynamic') __mapper_args__ = {'polymorphic_identity': 'client'} admin_id = db.Column(db.Integer, db.ForeignKey('admin.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): if modal_filters: main_query = Client.query.filter_by( account_id=modal_filters['account_id']) else: main_query = Client.query if term: result_qry = main_query.filter( or_(Client.email.like('%' + term + '%'), Client.displayname.like('%' + term + '%'))) else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(User.email.desc()) else: results_ord = result_qry.order_by(User.email.asc()) else: results_ord = result_qry.order_by(User.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results} def to_table_row(self): return { 'displayname': self.displayname, 'email': self.email, 'id': self.id, 'account_id': self.account_id } def to_dict(self): return { 'displayname': self.displayname, 'email': self.email, 'id': self.id, 'account_id': self.account_id } def populate_from_form(self, form): self.email = form.email.data self.displayname = form.displayname.data if form.password.data: self.password = encrypt_password(form.password.data) def check_admin(self): return False def get_user_type(self): return ROLE_CLIENT def check_client(self): return True def get_admin_id(self): return NotImplemented
class Landingpage(db.Model): ''' Class to represent landing page design ''' id = db.Column(db.Integer, primary_key=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) logofile = db.Column(db.String(200), default='/static/img/logo.png') bgfile = db.Column(db.String(200), default='/static/img/bg.jpg') pagebgcolor = db.Column(db.String(10), default='#ffffff') bgcolor = db.Column(db.String(10), default='#ffffff') headerlink = db.Column(db.String(200)) basefont = db.Column(db.Integer, default=2) topbgcolor = db.Column(db.String(10), default='#ffffff') toptextcolor = db.Column(db.String(10)) topfont = db.Column(db.Integer, default=2) toptextcont = db.Column(db.String(2000), default='Please Sign In for WiFi') middlebgcolor = db.Column(db.String(10), default='#ffffff') middletextcolor = db.Column(db.String(10)) middlefont = db.Column(db.Integer, default=2) bottombgcolor = db.Column(db.String(10), default='#ffffff') bottomtextcolor = db.Column(db.String(10)) bottomfont = db.Column(db.Integer, default=2) bottomtextcont = db.Column(db.String(2000)) footerbgcolor = db.Column(db.String(10), default='#ffffff') footertextcolor = db.Column(db.String(10)) footerfont = db.Column(db.Integer, default=2) footertextcont = db.Column(db.String(2000)) btnbgcolor = db.Column(db.String(10)) btntxtcolor = db.Column(db.String(10)) btnlinecolor = db.Column(db.String(10), default='#000000') tosfile = db.Column(db.String(200), default='/static/img/tos.pdf') copytextcont = db.Column(db.String(2000)) def populate_from_form(self, form): self.site_id = form.site_id.data self.logofile = form.logofile.data self.bgfile = form.bgfile.data self.pagebgcolor = form.pagebgcolor.data self.bgcolor = form.bgcolor.data self.headerlink = form.headerlink.data self.basefont = form.basefont.data self.topbgcolor = form.topbgcolor.data self.toptextcolor = form.toptextcolor.data self.topfont = form.topfont.data self.toptextcont = form.toptextcont.data self.middlebgcolor = form.middlebgcolor.data self.middletextcolor = form.middletextcolor.data self.middlefont = form.middlefont.data self.bottombgcolor = form.bottombgcolor.data self.bottomtextcolor = form.bottomtextcolor.data self.bottomfont = form.bottomfont.data self.footerbgcolor = form.footerbgcolor.data self.footertextcolor = form.footertextcolor.data self.footerfont = form.footerfont.data self.footertextcont = form.footertextcont.data self.btnbgcolor = form.btnbgcolor.data self.btntxtcolor = form.btntxtcolor.data self.btnlinecolor = form.btnlinecolor.data self.tosfile = form.tosfile.data self.copytextcont = form.copytextcont.data #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = Landingpage.query.filter( and_(Landingpage.site_id == modal_filters['siteid'], Landingpage.demo == False)) if term: result_qry = main_query else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(Landingpage.name.desc()) else: results_ord = result_qry.order_by(Landingpage.name.asc()) else: results_ord = result_qry.order_by(Landingpage.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results} def to_table_row(self): return {'name': self.name, 'site_id': self.site_id, 'id': self.id} def to_dict(self): return dict_normalise_values({ 'id': self.id, 'site_id': self.site_id, 'logofile': self.logofile, 'bgfile': self.bgfile, 'pagebgcolor': self.pagebgcolor, 'bgcolor': self.bgcolor, 'headerlink': self.headerlink, 'basefont': self.basefont, 'topbgcolor': self.topbgcolor, 'toptextcolor': self.toptextcolor, 'topfont': self.topfont, 'toptextcont': self.toptextcont, 'middlebgcolor': self.middlebgcolor, 'middletextcolor': self.middletextcolor, 'middlefont': self.middlefont, 'bottombgcolor': self.bottombgcolor, 'bottomtextcolor': self.bottomtextcolor, 'bottomfont': self.bottomfont, 'footerbgcolor': self.footerbgcolor, 'footertextcolor': self.footertextcolor, 'footerfont': self.footerfont, 'footertextcont': self.footertextcont, 'btnbgcolor': self.btnbgcolor, 'btntxtcolor': self.btntxtcolor, 'btnlinecolor': self.btnlinecolor, 'tosfile': self.tosfile, 'copytextcont': self.copytextcont })
class Wifisite(db.Model): ''' Class to represent wifi sites. Each client can have multiple sites ''' id = db.Column(db.Integer, primary_key=True) client_id = db.Column(db.Integer, db.ForeignKey('client.id')) admin_id = db.Column(db.Integer, db.ForeignKey('admin.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) name = db.Column(db.String(255), index=True, default="defaultsite") default_landing = db.Column(db.Integer) landingpages = db.relationship('Landingpage', backref='site', lazy='dynamic') guests = db.relationship('Guest', backref='site', lazy='dynamic') unifi_id = db.Column(db.String(50), index=True, default="default") devices = db.relationship('Device', backref='site', lazy='dynamic') sessions = db.relationship('Guestsession', backref='site', lazy='dynamic') guesttracks = db.relationship('Guesttrack', backref='site', lazy='dynamic') sitefiles = db.relationship('Sitefile', backref='site', lazy='dynamic') facebookauths = db.relationship('Facebookauth', backref='site', lazy='dynamic') vouchers = db.relationship('Voucher', backref='site', lazy='dynamic') template = db.Column(db.String(50), default='template1') emailformfields = db.Column(db.Integer, default=(FORM_FIELD_LASTNAME + FORM_FIELD_FIRSTNAME)) auth_method = db.Column(db.Integer, default=AUTH_TYPE_ALL) auth_fb_like = db.Column(db.Integer, default=FACEBOOK_LIKE_OFF) auth_fb_post = db.Column(db.Integer, default=FACEBOOK_POST_OFF) redirect_method = db.Column(db.Integer, default=REDIRECT_ORIG_URL) reports_type = db.Column(db.Integer, default=CLIENT_REPORT_WEEKLY) reports_list = db.Column(db.String(400)) enable_redirect = db.Column(db.Boolean()) redirect_url = db.Column(db.String(200)) fb_appid = db.Column(db.String(200)) fb_app_secret = db.Column(db.String(200)) fb_page = db.Column(db.String(200), default='https://www.facebook.com/unifyhotspot') timezone = db.Column(db.String(20), default='UTC') api_export = db.Column(db.Integer, default=API_END_POINT_NONE) api_auth_field1 = db.Column(db.String(200)) api_auth_field2 = db.Column(db.String(200)) api_auth_field3 = db.Column(db.String(200)) def populate_from_form(self, form): self.name = form.name.data self.unifi_id = form.unifi_id.data self.template = form.template.data self.enablehtml = form.enablehtml.data self.auth_method = (form.auth_fb.data and AUTH_TYPE_SOCIAL) + ( form.auth_phone.data and AUTH_TYPE_SMS) + (form.auth_voucher.data and AUTH_TYPE_VOUCHER) + ( form.auth_email.data and AUTH_TYPE_EMAIL) self.auth_fb_like = form.auth_fb_like.data self.auth_fb_post = form.auth_fb_post.data if self.account.en_advertisement: self.redirect_method = form.redirect_method.data self.redirect_url = form.redirect_url.data self.fb_page = form.fb_page.data self.timezone = form.timezone.data if self.account.en_fbauth_change: self.fb_appid = form.fb_appid.data self.fb_app_secret = form.fb_app_secret.data if self.account.en_reporting: self.reports_type = form.reports_type.data self.reports_list = form.reports_list.data self.emailformfields = (form.get_lastname.data and FORM_FIELD_LASTNAME ) + (form.get_firstname.data and FORM_FIELD_FIRSTNAME) if self.account.en_api_export: self.api_export = form.api_export.data self.api_auth_field1 = form.api_auth_field1.data self.api_auth_field2 = form.api_auth_field2.data self.api_auth_field3 = form.api_auth_field3.data def fb_login_en(self): return (self.auth_method & AUTH_TYPE_SOCIAL) def phone_login_en(self): return (self.auth_method & AUTH_TYPE_SMS) def voucher_login_en(self): return (self.auth_method & AUTH_TYPE_VOUCHER) def email_login_en(self): return (self.auth_method & AUTH_TYPE_EMAIL) def to_dict(self): reports_type = None reports_list = None fb_appid = None fb_app_secret = None redirect_method = None redirect_url = None api_export = None api_auth_field1 = None api_auth_field2 = None api_auth_field3 = None if self.account.en_reporting: reports_type = self.reports_type reports_list = self.reports_list if self.account.en_fbauth_change: fb_appid = self.fb_appid fb_app_secret = self.fb_app_secret if self.account.en_advertisement: redirect_method = self.redirect_method redirect_url = self.redirect_url if self.account.en_api_export: api_export = self.api_export api_auth_field1 = self.api_auth_field1 api_auth_field2 = self.api_auth_field2 api_auth_field3 = self.api_auth_field3 return dict_normalise_values({ 'name':self.name,'unifi_id':self.unifi_id, 'id':self.id, \ 'template':self.template, 'get_lastname': (self.emailformfields &FORM_FIELD_LASTNAME),\ 'get_firstname': (self.emailformfields &FORM_FIELD_FIRSTNAME),\ 'auth_fb':(self.auth_method &AUTH_TYPE_SOCIAL),'auth_email':(self.auth_method &AUTH_TYPE_EMAIL),\ 'auth_phone':(self.auth_method &AUTH_TYPE_SMS),'auth_voucher':(self.auth_method &AUTH_TYPE_VOUCHER),\ 'default_landing':self.default_landing,'reports_type':reports_type, \ 'fb_page':self.fb_page,'auth_fb_like':self.auth_fb_like,'auth_fb_post':self.auth_fb_post,\ 'fb_appid':fb_appid,'fb_app_secret':fb_app_secret, 'redirect_method':redirect_method,'redirect_url':redirect_url,'timezone':self.timezone,\ 'emailformfields':self.emailformfields,'reports_list':reports_list,'client_id':self.client.id,\ 'api_export':api_export,'api_auth_field1':api_auth_field1,'api_auth_field2':api_auth_field2,\ 'api_auth_field3':api_auth_field3}) #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = Wifisite.query.filter_by() if term: result_qry = main_query else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(Wifisite.name.desc()) else: results_ord = result_qry.order_by(Wifisite.name.asc()) else: results_ord = result_qry.order_by(Landingpage.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results}
self.file_label = form.file_label.data def update_ownership(self, request): siteid = request.view_args.get('siteid') self.site_id = siteid def get_file_path(self, fileid): if fileid == 0: return '/static/img/default_file.png' file_path = Sitefile.query.filter_by(id=fileid).first() return file_path vouchers_devices = db.Table( 'vouchers_devices', db.Column('voucher_id', db.Integer(), db.ForeignKey('voucher.id')), db.Column('device_id', db.Integer(), db.ForeignKey('device.id'))) #Store vouchers class Voucher(db.Model): id = db.Column(db.Integer, primary_key=True) batchid = db.Column(db.String(40), index=True) voucher = db.Column(db.String(20), index=True) notes = db.Column(db.String(50), index=True) duration_t = db.Column(db.BigInteger(), default=3600) bytes_t = db.Column(db.BigInteger(), default=1000) speed_dl = db.Column(db.BigInteger(), default=256) speed_ul = db.Column(db.BigInteger(), default=256) used = db.Column(db.Boolean(), default=False, index=True) num_devices = db.Column(db.Integer, default=1, index=True)
class Account(db.Model): ''' Class to represent accounts. Each account can have multiple clients and admins ''' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(60)) unifi_server = db.Column(db.String(255), index=True, default="localhost") unifi_server_ip = db.Column(db.String(255), index=True, default="127.0.0.1") unifi_user = db.Column(db.String(255), index=True, default="ubnt") unifi_pass = db.Column(db.String(255), index=True, default="ubnt") unifi_port = db.Column(db.Integer, index=True, default=8443) sites_allowed = db.Column(db.Integer, default=100) account_type = db.Column(db.Integer, index=True, default=ACCOUNT_TYPE_FREE) expiresat = db.Column(db.DateTime, index=True) en_api_export = db.Column(db.Integer, default=1, index=True) en_reporting = db.Column(db.Integer, default=1, index=True) en_analytics = db.Column(db.Integer, default=1, index=True) en_advertisement = db.Column(db.Integer, default=1, index=True) en_newsletter = db.Column(db.Integer, default=0, index=True) en_footer_change = db.Column(db.Integer, default=1, index=True) en_fbauth_change = db.Column(db.Integer, default=1, index=True) en_sms_preauth = db.Column(db.Integer, default=0, index=True) logins_allowed = db.Column(db.Integer, default=1000, index=True) firstrun = db.Column(db.Integer, default=1, index=True) token = db.Column(db.String(20), index=True) admins = db.relationship('Admin', backref='account', lazy='dynamic') clients = db.relationship('Client', backref='account', lazy='dynamic') sites = db.relationship('Wifisite', backref='account', lazy='dynamic') notifications = db.relationship('Notification', backref='account', lazy='dynamic') def populate_settings(self, form): self.unifi_server = form.unifi_server.data self.unifi_server_ip = form.unifi_server_ip.data self.unifi_user = form.unifi_user.data self.unifi_pass = form.unifi_pass.data self.unifi_port = form.unifi_port.data self.firstrun = 0 def get_settings(self): return dict_normalise_values({ 'unifi_server':self.unifi_server,'unifi_user':self.unifi_user, 'id':self.id, \ 'unifi_pass':self.unifi_pass,'unifi_server_ip':self.unifi_server_ip,'unifi_port':self.unifi_port} ) def populate_from_form(self, form): expiresat = datetime.datetime.strptime(form.expiresat.data, "%m/%d/%Y").date() self.unifi_server = form.unifi_server.data self.unifi_server_ip = form.unifi_server_ip.data self.unifi_user = form.unifi_user.data self.unifi_pass = form.unifi_pass.data self.unifi_port = form.unifi_port.data self.name = form.name.data self.sites_allowed = form.sites_allowed.data self.account_type = form.account_type.data self.expiresat = expiresat self.en_api_export = form.en_api_export.data self.en_reporting = form.en_reporting.data self.en_analytics = form.en_analytics.data self.en_advertisement = form.en_advertisement.data self.en_footer_change = form.en_footer_change.data self.en_fbauth_change = form.en_fbauth_change.data self.logins_allowed = form.logins_allowed.data def to_dict(self): expiresat = self.expiresat.strftime( "%m/%d/%Y") if self.expiresat else '' return dict_normalise_values({ 'unifi_server':self.unifi_server,'unifi_user':self.unifi_user, 'id':self.id, \ 'unifi_pass':self.unifi_pass,'name':self.name,'sites_allowed':self.sites_allowed,'account_type':self.account_type,\ 'expiresat':expiresat,'en_api_export':self.en_api_export,'en_reporting':self.en_reporting,\ 'en_analytics':self.en_analytics,'en_advertisement':self.en_advertisement,'en_footer_change':self.en_footer_change,\ 'en_fbauth_change':self.en_fbauth_change,'logins_allowed':self.logins_allowed, 'unifi_port':self.unifi_port } ) #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = Account.query if term: result_qry = main_query.filter(Account.name.like('%' + term + '%')) else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(Account.name.desc()) else: results_ord = result_qry.order_by(Account.name.asc()) if sort['column'] == "1": if sort['order'] == "desc": results_ord = result_qry.order_by(Account.sites_allowed.desc()) else: results_ord = result_qry.order_by(Account.sites_allowed.asc()) if sort['column'] == "2": if sort['order'] == "desc": results_ord = result_qry.order_by(Account.account_type.desc()) else: results_ord = result_qry.order_by(Account.account_type.asc()) if sort['column'] == "3": if sort['order'] == "desc": results_ord = result_qry.order_by(Account.expiresat.desc()) else: results_ord = result_qry.order_by(Account.expiresat.asc()) else: results_ord = result_qry.order_by(Account.name.desc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results} def to_table_row(self): expiresat = self.expiresat.strftime( "%m/%d/%Y") if self.expiresat else '' if self.account_type == ACCOUNT_TYPE_FREE: account_type = 'FREE' elif self.account_type == ACCOUNT_TYPE_SILVER: account_type = 'PERM' elif self.account_type == ACCOUNT_TYPE_GOLD: account_type = 'PERM' elif self.account_type == ACCOUNT_TYPE_GOLD_PREM: account_type = 'PERM' return dict_normalise_values({'name':self.name,'sites_allowed':self.sites_allowed,'account_type':account_type,\ 'expiresat':expiresat,'id':self.id} )
class Voucher(db.Model): id = db.Column(db.Integer, primary_key=True) batchid = db.Column(db.String(40), index=True) voucher = db.Column(db.String(20), index=True) notes = db.Column(db.String(50), index=True) duration_t = db.Column(db.BigInteger()) used = db.Column(db.Boolean(), default=False, index=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) duration = db.Column(db.String(20), index=True) used_at = db.Column( db.DateTime, index=True) #used time in UTC,filled once voucher is used device_id = db.Column(db.Integer, db.ForeignKey('device.id')) def populate_from_form(self, form): self.notes = form.notes.data #set duration accordingly if form.duration_t.data == 1: self.duration = form.duration.data + ' Hours' self.duration_t = int(form.duration.data) * 60 * 60 elif form.duration_t.data == 2: self.duration = form.duration.data + ' Days' self.duration_t = int(form.duration.data) * 60 * 60 * 24 elif form.duration_t.data == 3: self.duration = form.duration.data + ' Months' self.duration_t = int(form.duration.data) * 60 * 60 * 24 * 30 def to_dict(self): return { 'site': self.site.name, 'duration': self.duration, 'status': '<span class="label label-danger">Used</span>' if self.used else '<span class="label label-success">Initializing</span>', 'voucher': self.voucher, 'note': self.notes, 'id': self.id } return dict_server #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = Voucher.query.filter_by(site_id=modal_filters['siteid']) if term: result_qry = main_query.outerjoin(Voucher.site).filter( or_(Wifisite.name.like('%' + term + '%'), Voucher.voucher.like('%' + term + '%'), Voucher.notes.like('%' + term + '%'))) else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(Wifisite.name.desc()) else: results_ord = result_qry.order_by(Wifisite.name.asc()) elif sort['column'] == "1": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.voucher.desc()) else: results_ord = result_qry.order_by(Voucher.voucher.desc()) elif sort['column'] == "2": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.duration.desc()) else: results_ord = result_qry.order_by(Voucher.duration.desc()) elif sort['column'] == "3": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.used.desc()) else: results_ord = result_qry.order_by(Voucher.used.desc()) elif sort['column'] == "4": if sort['order'] == "desc": results_ord = result_qry.order_by(Voucher.notes.desc()) else: results_ord = result_qry.order_by(Voucher.notes.desc()) else: results_ord = result_qry.order_by(Voucher.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results} def to_table_row(self): return { 'site': self.site.name, 'duration': self.duration, 'status': '<span class="label label-danger">Used</span>' if self.used else '<span class="label label-primary">Available</span>', 'voucher': self.voucher, 'note': self.notes, 'id': self.id }
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) displayname = db.Column(db.String(255)) last_login_at = db.Column(db.String(255)) current_login_at = db.Column(db.String(255)) last_login_ip = db.Column(db.String(255)) current_login_ip = db.Column(db.String(255)) login_count = db.Column(db.Integer) confirmed_at = db.Column(db.String(255)) active = db.Column(db.Boolean()) type = db.Column(db.String(50)) __mapper_args__ = {'polymorphic_identity': 'user', 'polymorphic_on': type} def populate_from_form(self, form): self.email = form.email.data self.displayname = form.displayname.data if form.password.data: self.password = encrypt_password(form.password.data) def to_dict(self): return dict_normalise_values({ 'id': self.id, 'email': self.email, 'displayname': self.displayname }) def __get_obj(self, obj, obj_id): if obj_id: obj_instance = obj.query.filter_by(id=obj_id).first() if obj_instance: return obj_instance #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self, term, offset=0, limit=10, sort=None, modal_filters=None): main_query = User.query.filter_by() if term: result_qry = main_query.filter( or_(User.email.like('%' + term + '%'), User.displayname.like('%' + term + '%'))) else: result_qry = main_query result_qry = result_qry.distinct() total = result_qry.count() if sort['column'] == "0": if sort['order'] == "desc": results_ord = result_qry.order_by(User.email.desc()) else: results_ord = result_qry.order_by(User.email.asc()) else: results_ord = result_qry.order_by(User.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total': total, 'results': results}
class Notification(db.Model): ''' Class to represent notifications. ''' id = db.Column(db.Integer, primary_key=True) content = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow, index=True) viewed = db.Column(db.Boolean(), default=0, index=True) viewed_at = db.Column(db.DateTime) user_id = db.Column(db.Integer, index=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) notifi_type = db.Column(db.Integer, index=True) notifi_id = db.Column(db.String(20), index=True) @classmethod def get_common_notifications(cls, account_id): notifications = Notification.query.filter_by( viewed=0, user_id=0, account_id=account_id).all() return notifications @classmethod def get_user_notifications(cls, account_id, user_id): notifications = Notification.query.filter_by( viewed=0, user_id=user_id, account_id=account_id).all() return notifications @classmethod def mark_as_read(cls, id, account_id): notification = Notification.query.filter_by( id=id, account_id=account_id).first() if not notification: return None notification.viewed = 1 notification.viewed_at = arrow.now().naive db.session.commit() return 1 @classmethod def mark_as_unread(cls, id, account_id): notification = Notification.query.filter_by( id=id, account_id=account_id).first() if not notification: return None notification.viewed = 0 notification.viewed_at = None db.session.commit() return 1 @classmethod def check_notify_added(cls, notifi_id): if Notification.query.filter_by(notifi_id=notifi_id).first(): return True return False def get_type(self): if self.notifi_type == NOTIFI_TYPE_DANGER: return 'danger' elif self.notifi_type == NOTIFI_TYPE_INFO: return 'info' elif self.notifi_type == NOTIFI_TYPE_SUCCESS: return 'success' elif self.notifi_type == NOTIFI_TYPE_WARNING: return 'warning' else: return '' def to_dict(self): return dict_normalise_values({'id':self.id, \ 'content':self.content,'account_id':self.account_id,'user_id':self.user_id,\ 'notifi_type':self.notifi_type,'notifi_id':self.notifi_id\ })
from flask_sqlalchemy import SQLAlchemy, SignallingSession, SessionBase from flask_security import RoleMixin, UserMixin from flask_security.utils import encrypt_password from flask_security import SQLAlchemyUserDatastore from unifispot.extensions import db from unifispot.base.utils.helper import dict_normalise_values from unifispot.const import ROLE_ADMIN, ROLE_CLIENT #Roles for flask-security roles_users = db.Table( 'roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) class Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) def __repr__(self): return "<Role Name:%s Description:%s>" % (self.name, self.description) #going to use joined table inheritance as given in http://docs.sqlalchemy.org/en/rel_1_0/orm/inheritance.html#joined-table-inheritance class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) roles = db.relationship('Role', secondary=roles_users,
class Sitestat(db.Model): ''' Class to represent daily statistics ''' id = db.Column(db.Integer, primary_key=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) date = db.Column(db.DateTime, index=True) #used as key num_visits = db.Column(db.Integer, default=0) num_newlogins = db.Column(db.Integer, default=0) num_repeats = db.Column(db.Integer, default=0) num_emails = db.Column(db.Integer, default=0) num_fb = db.Column(db.Integer, default=0) num_vouchers = db.Column(db.Integer, default=0) num_phones = db.Column(db.Integer, default=0) num_checkins = db.Column(db.Integer, default=0) num_likes = db.Column(db.Integer, default=0) avg_time = db.Column(db.Integer, default=0) avg_data = db.Column(db.Integer, default=0) last_updated = db.Column(db.DateTime, default=datetime.datetime.utcnow, index=True) def get_total_logins(self): '''returns total logins for the day ''' return self.num_newlogins + self.num_repeats def __add__(self, other): '''Add two sitestat objects, used for calculating weekly and monthly status ''' return Sitestat(num_visits=int(self.num_visits) + int(other.num_visits), num_newlogins=self.num_newlogins + other.num_newlogins, num_repeats=self.num_repeats + other.num_repeats, num_emails=self.num_emails + other.num_emails, num_fb=self.num_fb + other.num_fb, num_vouchers=self.num_vouchers + other.num_vouchers, num_phones=self.num_phones + other.num_phones, num_checkins=self.num_checkins + other.num_checkins, num_likes=self.num_likes + other.num_likes) @classmethod def get_dashboard_stats(cls, daystats): logins = [] newlogins = [] likes = [] checkins = [] maxlogin = 0 maxsocial = 0 total_visits = 0 total_logins = 0 total_likes = 0 total_checkins = 0 total_emails = 0 total_vouchers = 0 total_fbs = 0 total_phones = 0 for daystat in daystats: timestamp = arrow.get(daystat.date).timestamp * 1000 today_logins = daystat.get_total_logins() today_newlogins = daystat.num_newlogins total_visits += daystat.num_visits total_logins += today_logins total_likes += daystat.num_likes total_checkins += daystat.num_checkins total_emails += daystat.num_emails total_vouchers += daystat.num_vouchers total_fbs += daystat.num_fb total_phones += daystat.num_phones logins.append([timestamp, today_logins]) newlogins.append([timestamp, today_newlogins]) likes.append([timestamp, daystat.num_likes]) checkins.append([timestamp, daystat.num_checkins]) if today_logins > maxlogin: maxlogin = today_logins if daystat.num_likes > maxsocial: maxsocial = daystat.num_likes if daystat.num_checkins > maxsocial: maxsocial = daystat.num_checkins return { 'status': 1, 'logins': logins, 'newlogins': newlogins, 'maxlogin': maxlogin, 'total_visits': total_visits, 'total_logins': total_logins, 'total_likes': total_likes, 'total_checkins': total_checkins, 'total_emails': total_emails, 'total_phones': total_phones, 'total_fbs': total_fbs, 'total_vouchers': total_vouchers, 'likes': likes, 'checkins': checkins, 'maxsocial': maxsocial } @classmethod def get_combine_stats(cls, daystats): logins = {} newlogins = {} likes = {} checkins = {} maxlogin = 0 maxsocial = 0 total_visits = 0 total_logins = 0 total_likes = 0 total_checkins = 0 total_emails = 0 total_vouchers = 0 total_fbs = 0 total_phones = 0 def dict_to_list(dict): lst = [] for key in sorted(dict): lst.append([key, dict[key]]) return lst for daystat in daystats: timestamp = arrow.get(daystat.date).timestamp * 1000 today_logins = daystat.get_total_logins() today_newlogins = daystat.num_newlogins total_visits += daystat.num_visits total_logins += today_logins total_likes += daystat.num_likes total_checkins += daystat.num_checkins total_emails += daystat.num_emails total_vouchers += daystat.num_vouchers total_fbs += daystat.num_fb total_phones += daystat.num_phones #update daily like/checkin/login/newlogins if logins.get(timestamp): logins[timestamp] += today_logins else: logins[timestamp] = today_logins if newlogins.get(timestamp): newlogins[timestamp] += today_newlogins else: newlogins[timestamp] = today_newlogins if likes.get(timestamp): likes[timestamp] += daystat.num_likes else: likes[timestamp] = daystat.num_likes if checkins.get(timestamp): checkins[timestamp] += daystat.num_checkins else: checkins[timestamp] = daystat.num_checkins maxlogin = max(logins.values()) maxsocial = max(max(checkins.values()), max(likes.values())) return { 'status': 1, 'logins': dict_to_list(logins), 'newlogins': dict_to_list(newlogins), 'maxlogin': maxlogin, 'total_visits': total_visits, 'total_logins': total_logins, 'total_likes': total_likes, 'total_checkins': total_checkins, 'total_emails': total_emails, 'total_phones': total_phones, 'total_fbs': total_fbs, 'total_vouchers': total_vouchers, 'likes': dict_to_list(likes), 'checkins': dict_to_list(checkins), 'maxsocial': maxsocial }
class Guest(db.Model): ''' Class to represent guest profile, it will be filled fully/partially depending upon site configuration ''' id = db.Column(db.Integer, primary_key=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) firstname = db.Column(db.String(60)) lastname = db.Column(db.String(60)) age = db.Column(db.Integer,index=True) gender = db.Column(db.Integer,index=True) state = db.Column(db.Integer,index=True) email = db.Column(db.String(60)) phonenumber = db.Column(db.String(15)) devices = db.relationship('Device', backref='guest',lazy='dynamic') fb_profile = db.Column(db.Integer, db.ForeignKey('facebookauth.id')) fb_liked = db.Column(db.Integer) fb_posted = db.Column(db.Integer) created_at = db.Column(db.DateTime,default=datetime.datetime.utcnow,index=True) apisync = db.Column(db.Integer,index=False) #Flag to be set after syncing to API synchedat = db.Column(db.DateTime,index=True) #synched time in UTC demo = db.Column(db.Boolean(),default=0,index=True) newsletter = db.Column(db.Boolean(),default=0,index=True) dob = db.Column(db.String(15)) details = db.Column(db.Text) def get_device_phonenumber(self): for device in self.devices: phonenumber = device.get_phonenumber() if phonenumber: return phonenumber return '' def get_gender(self): if self.gender == 1 : return 'M' elif self.gender == 2: return 'F' else: return 'N/A' def populate_from_email_form(self,form,form_fields): details = '' if hasattr(form,'email'): self.email = form.email.data if hasattr(form,'firstname'): self.firstname = form.firstname.data if hasattr(form,'lastname'): self.lastname = form.lastname.data if hasattr(form,'phonenumber'): self.phonenumber = form.phonenumber.data if hasattr(form,'dob'): self.dob = form.dob.data if hasattr(form,'newsletter'): self.newsletter = form.newsletter.data if hasattr(form,'extra1'): details += '%s:%s '%(form.extra1.label.text,form.extra1.data) if hasattr(form,'extra2'): details += '%s:%s'%(form.extra2.label.text,form.extra2.data) self.details = details def search_query(self,term,offset=0,limit=10,sort=None,modal_filters=None): main_query = Guest.query.filter(and_(Guest.site_id==modal_filters['siteid'],Guest.demo ==0, Guest.created_at >= modal_filters['startdate'],Guest.created_at <= modal_filters['enddate'])) if term: result_qry = main_query else: result_qry = main_query result_qry = result_qry.distinct( ) total = result_qry.count() if sort['column'] == "0" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.firstname.desc()) else: results_ord = result_qry.order_by(Guest.firstname.asc()) elif sort['column'] == "1" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.lastname.desc()) else: results_ord = result_qry.order_by(Guest.lastname.asc()) elif sort['column'] == "2" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.age.desc()) else: results_ord = result_qry.order_by(Guest.age.asc()) elif sort['column'] == "3" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.gender.desc()) else: results_ord = result_qry.order_by(Guest.gender.asc()) elif sort['column'] == "4" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.phonenumber.desc()) else: results_ord = result_qry.order_by(Guest.phonenumber.asc()) elif sort['column'] == "5" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.email.desc()) else: results_ord = result_qry.order_by(Guest.email.asc()) elif sort['column'] == "6" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guest.created_at.desc()) else: results_ord = result_qry.order_by(Guest.created_at.asc()) else: results_ord = result_qry.order_by(Guest.firstname.asc()) results = results_ord.offset(offset).limit(limit).all() print {'total':total,'results':results} return {'total':total,'results':results} def to_table_row(self): created_at = self.created_at.strftime("%d/%m/%Y") if self.created_at else '' phonenumber = self.phonenumber if self.phonenumber else self.get_device_phonenumber() newsletter = 'yes' if self.newsletter else 'no' return {'firstname':self.firstname,'age':self.age,'email':self.email, 'lastname':self.lastname,'phonenumber':self.phonenumber, 'id':self.id,'gender':self.get_gender(),'created_at':created_at,'site_id':self.site_id, 'newsletter':self.newsletter,'dob':self.dob,'details':self.details } def to_dict(self): created_at = self.created_at.strftime("%d/%m/%Y") if self.created_at else '' phonenumber = self.phonenumber if self.phonenumber else self.get_device_phonenumber() newsletter = 'yes' if self.newsletter else 'no' return {'firstname':self.firstname,'age':self.age,'email':self.email, 'lastname':self.lastname,'phonenumber':self.phonenumber, 'id':self.id,'gender':self.get_gender(),'created_at':created_at,'site_id':self.site_id, 'newsletter':self.newsletter,'dob':self.dob,'details':self.details } def to_list(self): created_at = self.created_at.strftime("%d/%m/%Y") if self.created_at else '' phonenumber = self.phonenumber if self.phonenumber else self.get_device_phonenumber() newsletter = 'yes' if self.newsletter else 'no' #convert to list add replace None by '' list_to_clean = [self.firstname,self.lastname,self.email,created_at,phonenumber,self.age,self.get_gender(),\ newsletter,self.dob,self.details] return [x.encode('ascii','ignore') if x else '' for x in list_to_clean] def get_csv_headers(self): return ['Firstname','Lastname','Email','Created On','Phone','Age','Gender',"Newsletter",'DOB','Details']
class Guesttrack(db.Model): ''' Class to track connection attempts, this is also used to track login process ''' id = db.Column(db.Integer, primary_key=True) track_id = db.Column(db.String(40),index=True,unique=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) session_id = db.Column(db.Integer, db.ForeignKey('guestsession.id')) ap_mac = db.Column(db.String(20),index=True) device_mac = db.Column(db.String(20),index=True) timestamp = db.Column(db.DateTime,default=datetime.datetime.utcnow,index=True) state = db.Column(db.Integer,index=True) fb_liked = db.Column(db.Integer,index=True,default=0) fb_posted = db.Column(db.Integer,index=True,default=0) orig_url = db.Column(db.String(200)) demo = db.Column(db.Integer,default=0,index=True) duration = db.Column(db.Integer,default=60) #Duration authorized in minutes temp_login = db.Column(db.Integer,default=0) def is_authorized(self): '''Return True if the guest_track is marked as authorized ''' if self.state == GUESTRACK_SMS_AUTH and self.site.phone_login_en(): return True elif self.state == GUESTRACK_EMAIL_AUTH and self.site.email_login_en(): return True elif self.state == GUESTRACK_VOUCHER_AUTH and self.site.voucher_login_en(): return True elif self.state == GUESTRACK_SOCIAL_AUTH and self.site.fb_login_en(): return True elif self.state == GUESTRACK_PREAUTH: return True else: return False def is_temp_authorized(self): ''' Return True if guest_track marked for is_temp_authorized ''' if self.state == GUESTRACK_SOCIAL_PREAUTH: return True else: return False
class Guestsession(db.Model): ''' Class to represent guest session. Each session is associated to a Guest and will have a state associated with it. ''' id = db.Column(db.Integer, primary_key=True) site_id = db.Column(db.Integer, db.ForeignKey('wifisite.id')) device_id = db.Column(db.Integer, db.ForeignKey('device.id')) voucher_id = db.Column(db.Integer, db.ForeignKey('voucher.id')) starttime = db.Column(db.DateTime,default=datetime.datetime.utcnow,index=True) lastseen = db.Column(db.DateTime,index=True,default=datetime.datetime.utcnow) stoptime = db.Column(db.DateTime,index=True) #Time at which session is stopped, to be filled by session updator expiry = db.Column(db.DateTime,index=True,default=datetime.datetime.utcnow) #predicted expiry time,default to 60 minutes temp_login = db.Column(db.Integer,default=0) duration = db.Column(db.Integer,default=60) ban_ends = db.Column(db.DateTime,index=True) data_used = db.Column(db.String(20),default=0) #Data used up in this session state = db.Column(db.Integer) mac = db.Column(db.String(30),index=True) d_updated = db.Column(db.String(20)) #data updated last guesttracks = db.relationship('Guesttrack', backref='guestsession',lazy='dynamic') demo = db.Column(db.Integer,default=0,index=True) obj_id = db.Column(db.String(30),index=True) #_id of document in guest collection of unifi #Search option with paging and sorting, uses LIKE on INDEXED fields #and return num of total results as well as number of rows controlled by paging def search_query(self,term,offset=0,limit=10,sort=None,modal_filters=None): main_query = Guestsession.query.filter(and_(Guestsession.site_id==modal_filters['siteid'], Guestsession.starttime >= modal_filters['startdate'],Guestsession.starttime <= modal_filters['enddate'], Guestsession.obj_id != None)) if term: result_qry = main_query else: result_qry = main_query result_qry = result_qry.distinct( ) total = result_qry.count() if sort['column'] == "0" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guestsession.starttime.desc()) else: results_ord = result_qry.order_by(Guestsession.starttime.asc()) elif sort['column'] == "1" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guestsession.stoptime.desc()) else: results_ord = result_qry.order_by(Guestsession.stoptime.asc()) elif sort['column'] == "2" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guestsession.mac.desc()) else: results_ord = result_qry.order_by(Guestsession.mac.asc()) elif sort['column'] == "3" : if sort['order'] == "desc": results_ord = result_qry.order_by(Guestsession.data_used.desc()) else: results_ord = result_qry.order_by(Guestsession.data_used.asc()) else: results_ord = result_qry.order_by(Guestsession.id.asc()) results = results_ord.offset(offset).limit(limit).all() return {'total':total,'results':results} def to_table_row(self): site = self.site stoptime = 'N/A' starttime = arrow.get(self.starttime).to(site.timezone).format('DD-MM-YYYY HH:mm:ss') if self.stoptime: stoptime = arrow.get(self.stoptime).to(site.timezone).format('DD-MM-YYYY HH:mm:ss') #get data_used and convert to Mb dta = int(self.data_used) if self.data_used else 0 data_used = str(math.ceil((dta/1024000.0))) return {'id':self.id,'stoptime':stoptime,'starttime':starttime, 'mac':self.mac,'data_used':data_used,'phonenumber':self.device.get_phonenumber() } def to_list(self): site = self.site starttime = arrow.get(self.starttime).to(site.timezone).format('DD-MM-YYYY HH:mm:ss') stoptime = 'N/A' if self.stoptime: stoptime = arrow.get(self.stoptime).to(site.timezone).format('DD-MM-YYYY HH:mm:ss') #get data_used and convert to Mb dta = int(self.data_used) if self.data_used else 0 data_used = str(math.ceil((dta/1024000.0))) list_to_clean = [ starttime,stoptime,self.mac,data_used,self.device.get_phonenumber()] return [x if x else '' for x in list_to_clean]