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)
class Fbconfig(CRUDMixin, SerializerMixin, db.Model): id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) auth_fb_like = db.Column(db.Integer, default=FACEBOOK_LIKE_OFF) auth_fb_post = db.Column(db.Integer, default=FACEBOOK_POST_OFF) fb_appid = db.Column(db.String(200)) fb_app_secret = db.Column(db.String(200)) fb_page = db.Column( db.Text, default='https://www.facebook.com/Unifispot-1652553388349756') data_limit = db.Column(db.BigInteger, default=0) time_limit = db.Column(db.Integer, default=60) speed_ul = db.Column(db.Integer, default=0) speed_dl = db.Column(db.Integer, default=0) session_limit_control = db.Column(db.Integer) session_overridepass = db.Column(db.String(50)) relogin_policy = db.Column(db.String(25), default='onetime') site = db.relationship(Wifisite, backref=db.backref("fbconfigs", \ cascade="all,delete")) #serializer arguement __json_hidden__ = [] __json_modifiers__ = {} __form_fields_avoid__ = ['id', 'siteid', 'account_id'] __form_fields_modifiers__ = {}
class Sitefile(db.Model): ''' Class to represent Files, each entry will point to a file stored in the HD ''' id = db.Column(db.Integer, primary_key=True) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) file_location = db.Column(db.String(255)) file_label = db.Column(db.String(255)) site = db.relationship(Wifisite, backref=db.backref("sitefiles", cascade="all,delete")) def to_dict(self): return { 'file_location': self.file_location, 'id': self.id, 'file_label': self.file_label } def populate_from_form(self, form): self.file_label = form.file_label.data def update_ownership(self, siteid): self.siteid = 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
class Device(CRUDMixin, SerializerMixin, db.Model): ''' Class to represent guest's device, each guest can have multiple devices attached to his account ''' id = db.Column(db.Integer, primary_key=True) devicemac = db.Column(db.String(30), index=True) hostname = db.Column(db.String(60), index=True) state = db.Column(db.Integer) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow, index=True) guestid = db.Column(db.Integer, db.ForeignKey('guest.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) expires_at = db.Column(db.DateTime) #Expiry time for last used voucher demo = db.Column(db.Integer, default=0, index=True) sms_confirm = db.Column( db.Integer, default=0, index=True) #used to verify if the device's phone number is confirmed guest = db.relationship(Guest, backref=db.backref("devices", \ cascade="all,delete")) loginauths = db.relationship('Loginauth', backref='device',\ lazy='dynamic') def get_monthly_usage(self): '''Returns the total monthly free data usage for this device Excludes voucher usage ''' firstday = arrow.now(self.site.timezone).floor('month').to('UTC').naive sessions = Guestsession.query.filter( and_(Guestsession.device_id == self.id, Guestsession.starttime >= firstday)).all() total_data = 0 for session in sessions: if session.state != GUESTRACK_VOUCHER_AUTH and session.data_used: total_data += int(session.data_used) #convert bytes to Mb data_mb = int(math.ceil((total_data / 1024000.0))) return data_mb def get_phonenumber(self): '''Returns the phonenumber connected to this account ''' return ';'.join([x.phonenumber for x in self.smsdatas]) def get_voucher(self): '''Returns a valid voucher id if any associated with this device, if nothing found returns None ''' for voucher in self.vouchers: if voucher.check_validity(): return voucher.id return None
class Guesttrack(CRUDMixin, SerializerMixin, db.Model): ''' Class to track connection attempts, this is also used to track login process ''' id = db.Column(db.Integer, primary_key=True) trackid = db.Column(db.String(40), index=True, unique=True) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) preloginauthid = db.Column(db.Integer, db.ForeignKey('preloginauth.id')) loginauthid = db.Column(db.Integer, db.ForeignKey('loginauth.id')) deviceid = db.Column(db.Integer, db.ForeignKey('device.id')) apmac = db.Column(db.String(20), index=True) devicemac = 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, default=GUESTTRACK_PRELOGIN) origurl = db.Column(db.String(200)) demo = db.Column(db.Integer, default=0, index=True) site = db.relationship(Wifisite, backref=db.backref("guesttracks", cascade="all,delete")) loginstat = db.Column(JSONEncodedDict(255)) #store relevant stats # will have value like {'auth_facebook':1, # 'fb_liked':1,'newlogin':1} extrainfo = db.Column(JSONEncodedDict(500)) #to store extra info def updatestat(self, key, val): '''method to update statistics value for this track ''' oldstat = dict(self.loginstat) oldstat[key] = val self.loginstat = oldstat self.save() def increamentstat(self, key): '''method to increament value of stat for a particular key ''' oldstat = dict(self.loginstat) if self.loginstat else {} oldval = oldstat.get(key) if oldval: oldstat[key] = oldval + 1 else: oldstat[key] = 1 self.loginstat = oldstat self.save() def updateextrainfo(self, key, val): '''method to update extrainfo value for this track ''' oldinfo = dict(self.extrainfo) oldinfo[key] = val self.extrainfo = oldinfo self.save()
class Phoneauth(Loginauth): __mapper_args__ = {'polymorphic_identity': 'phoneauth'} smsauthcode = db.Column(db.String(10),index=True) smsauthgenerated_at = db.Column(db.DateTime,index=True) smsauthconfirmed_at = db.Column(db.DateTime,index=True) smsauthtries = db.Column(db.Integer,default=0) smsauthstate = db.Column(db.Integer,default=0) def get_stat(self): if self.is_valid(): if self.relogin: return { 'auth_email':1,'relogin':1} else: return { 'auth_email':1,'relogin':0} else: return { 'auth_email':0 } def activate(self,emailconfig): '''Activate an emailloginauth ''' return NotImplemented self.state = LOGINAUTH_READY self.activatedat = arrow.utcnow().naive self.save()
class Options(CRUDMixin, SerializerMixin, db.Model): ''' Class to represent general Options. ''' id = db.Column(db.Integer, primary_key=True) option_name = db.Column(db.String(255), index=True) option_value = db.Column(db.Text) account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
class Voucherdesign(CRUDMixin,SerializerMixin,db.Model): ''' Class to represent Voucher design ''' id = db.Column(db.Integer, primary_key=True) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) logofile = db.Column(db.String(200),default='/static/img/logo.png') showlogo = db.Column(db.Integer,default=1) shownotes = db.Column(db.Integer,default=1) showqr = db.Column(db.Integer,default=1) showduration = db.Column(db.Integer,default=1) showdata = db.Column(db.Integer,default=1) showspeed = db.Column(db.Integer,default=1) bgcolor = db.Column(db.String(10),default='#ffffff') txtcolor = db.Column(db.String(10),default='#000000') bordercolor = db.Column(db.String(10),default='#000000') __form_fields_avoid__ = ['id','siteid','account_id']
class Guestsession(CRUDMixin, SerializerMixin, 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) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) deviceid = db.Column(db.Integer, db.ForeignKey('device.id')) loginauthid = db.Column(db.Integer, db.ForeignKey('loginauth.id')) trackid = db.Column(db.Integer, db.ForeignKey('guesttrack.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=0) override = db.Column( db.Integer, default=0 ) # to disable considering the session from considering while usage calculation 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 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 site = db.relationship(Wifisite, backref=db.backref("guestsessions")) loginauth = db.relationship(Loginauth, backref=db.backref("sessions", \ cascade="all,delete")) guesttrack = db.relationship(Guesttrack, backref=db.backref("sessions", \ cascade="all,delete"))
class Account(CRUDMixin, SerializerMixin, db.Model): ''' Class to general settings ''' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text) 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) unifi_version = db.Column(db.String(5), index=True, default='v4') mysql_server = db.Column(db.String(255), index=True, default="localhost") mysql_user = db.Column(db.String(255), index=True, default="ubnt") mysql_pass = db.Column(db.String(255), index=True, default="ubnt") mysql_port = db.Column(db.Integer, index=True, default=8443) firstrun = db.Column(db.Integer, default=1, index=True) token = db.Column(db.String(50), index=True) db_version = db.Column(db.String(5), index=True) expiresat = db.Column(db.DateTime, index=True) createdat = db.Column(db.DateTime, index=True) capabilities = db.Column(db.Integer, index=True) active = db.Column(db.Integer, default=1, index=True) logins_allowed = db.Column(db.Integer, default=1000, index=True) notifications = db.relationship('Notification', backref='account', lazy='dynamic') #serialiser arguement __json_public__ = [ 'id', 'unifi_server', 'unifi_user', 'unifi_pass', 'unifi_port' ] __form_fields_avoid__ = [ 'id', 'firstrun', 'token', 'db_version', 'account_type', 'expiresat', 'capabilities', 'logins_allowed', 'active', 'mysql_server', 'mysql_user', 'mysql_pass', 'mysql_port', 'name', 'unifi_server_ip', 'createdat' ]
class Emailconfig(LoginconfigMixin,CRUDMixin,SerializerMixin,db.Model): id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) enable_fields = db.Column(JSONEncodedDict(255)) mandate_fields = db.Column(JSONEncodedDict(255)) labelfor_fields = db.Column(JSONEncodedDict(255)) data_limit = db.Column(db.BigInteger,default=0) time_limit = db.Column(db.Integer,default=60) speed_ul = db.Column(db.Integer,default=0) speed_dl = db.Column(db.Integer,default=0) session_limit_control= db.Column(db.Integer) session_overridepass = db.Column(db.String(50)) relogin_policy = db.Column(db.String(25),default='onetime') site = db.relationship(Wifisite, backref=db.backref("emailconfigs", \ cascade="all,delete")) def __init__(self): '''Initial values for fields ''' self.enable_fields = {'enable_email': 1, 'enable_firstname':1, 'enable_lastname':1,'enable_dob':0, 'enable_extra1':0,'enable_extra2':0 } self.mandate_fields = {'mandate_email': 1, 'mandate_firstname':1, 'mandate_lastname':1,'mandate_dob':0, 'mandate_extra1':0,'mandate_extra2':0 } self.labelfor_fields = {'labelfor_email': 'Email Address', 'labelfor_firstname':'First Name', 'labelfor_lastname':'Last Name','labelfor_dob':'', 'labelfor_extra1':'','labelfor_extra2':'' } #serializer arguement __json_hidden__ = [] __json_modifiers__ = { 'enable_fields':'modeljson_to_dict', 'mandate_fields':'modeljson_to_dict', 'labelfor_fields':'modeljson_to_dict'} __form_fields_avoid__ = ['id','siteid','account_id'] __form_fields_modifiers__ = { 'enable_fields':'form_to_modeljson', 'mandate_fields':'form_to_modeljson', 'labelfor_fields':'form_to_modeljson', }
class TestModel(SerializerMixin, CRUDMixin, _db.Model): id = _db.Column(_db.Integer, primary_key=True) column1 = _db.Column(_db.String(255)) column2 = _db.Column(_db.String(255)) column3 = _db.Column(_db.String(255)) column4 = _db.Column(_db.String(255)) def test_mod_form(self, form, data): return 'random' def test_mod_dict(self, key): return {key: 'random'} __form_fields_modifiers__ = { 'column2': test_mod_form, 'column4': 'test_mod_form' } __form_fields_avoid__ = ['id', 'column3'] __json_hidden__ = ['column1'] __json_modifiers__ = {'column3': test_mod_dict, 'column4': 'test_mod_dict'}
class WifisiteFactory(BaseFactory): name = 'admin' default_landing = 1 backend = db.Column(db.String(50)) template = 'default' reports_type = 0 reports_list = '' redirect_url = 'http://www.unifispot.com' timezone = 'UTC' class Meta: """Factory configuration.""" model = Wifisite
class Preloginauth(SerializerMixin, db.Model): '''Base class to store preoginauth credentials, could be SMS or something All logins should be inherited from this class ''' id = db.Column(db.Integer, primary_key=True) client_id = db.Column(db.Integer, db.ForeignKey('client.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) tracks = db.relationship('Guesttrack', backref='preloginauth',\ lazy='dynamic') site = db.relationship(Wifisite, backref=db.backref("preloginauths", \ cascade="all,delete")) type = db.Column(db.String(50)) __mapper_args__ = { 'polymorphic_identity': 'preloginauth', 'polymorphic_on': type }
class Fbauth(Loginauth): fbprofileid = db.Column(db.String(200), index=True) fbtoken = db.Column(db.Text) fbliked = db.Column(db.Integer, default=0, index=True) fbcheckedin = db.Column(db.Integer, default=0, index=True) __mapper_args__ = {'polymorphic_identity': 'fbauth'} def reset_lastlogin(self): self.last_login_at = arrow.utcnow().naive self.fbcheckedin = 0 self.save() def login_completed(self, loginconfig): if self.state == LOGINAUTH_INIT: return False elif loginconfig.auth_fb_like and not self.fbliked: return False elif loginconfig.auth_fb_post and not self.fbcheckedin: return False else: return True
class User(CRUDMixin, SerializerMixin, 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.DateTime) current_login_at = db.Column(db.DateTime) last_login_ip = db.Column(db.String(100)) current_login_ip = db.Column(db.String(100)) login_count = db.Column(db.Integer) confirmed_at = db.Column(db.DateTime) active = db.Column(db.Boolean(), default=1) type = db.Column(db.String(50)) __mapper_args__ = {'polymorphic_identity': 'user', 'polymorphic_on': type} #serialiser arguement __json_hidden__ = ['password'] __json_modifiers__ = { 'last_login_at': FORMAT_DATETIME, 'current_login_at': FORMAT_DATETIME, 'confirmed_at': FORMAT_DATETIME } 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 set_password(self, password): self.password = encrypt_password(password) db.session.commit() def __repr__(self): return "<User Name:%s Email:%s>" % (self.displayname, self.email)
class Fbconfig(LoginconfigMixin, CRUDMixin, SerializerMixin, db.Model): id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) auth_fb_like = db.Column(db.Integer, default=FACEBOOK_LIKE_OFF) auth_fb_post = db.Column(db.Integer, default=FACEBOOK_POST_OFF) fb_appid = db.Column(db.String(200)) fb_app_secret = db.Column(db.String(200)) fb_page = db.Column( db.Text, default='https://www.facebook.com/Unifispot-1652553388349756') data_limit = db.Column(db.BigInteger, default=0) time_limit = db.Column(db.Integer, default=60) speed_ul = db.Column(db.Integer, default=0) speed_dl = db.Column(db.Integer, default=0) session_limit_control = db.Column(db.Integer) session_overridepass = db.Column(db.String(50)) relogin_policy = db.Column(db.String(25), default='onetime') optinout_fields = db.Column(JSONEncodedDict(255)) fbprofile_fields = db.Column(JSONEncodedDict(255)) site = db.relationship(Wifisite, backref=db.backref("fbconfigs", \ cascade="all,delete")) #serializer arguement __json_hidden__ = [] json_modifiers__ = { 'optinout_fields': 'modeljson_to_dict', 'fbprofile_fields': 'modeljson_to_dict', } __form_fields_avoid__ = ['id', 'siteid', 'account_id'] __form_fields_modifiers__ = { 'optinout_fields': 'form_to_modeljson', 'fbprofile_fields': 'form_to_modeljson' } def optinout_enabled(self): if self.optinout_fields and self.optinout_fields.get( 'optinout_enable'): return 1 else: return 0 def get_extra_profile_fields(self): '''return extra fields to be collected from facebook user should return a string of permissions seperated by comma https://developers.facebook.com/docs/facebook-login/permissions#reference-user_location ''' fields = [] fbprofile_fields = self.fbprofile_fields or {} if fbprofile_fields.get('fbprofile_birthday'): fields.append('user_birthday') if fbprofile_fields.get('fbprofile_location'): fields.append('user_location') if fields: return ','.join(fields) else: return ''
class Guest(ExportMixin, CRUDMixin, SerializerMixin, 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) siteid = 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.String(10), index=True) state = db.Column(db.Integer, index=True) fbcheckedin = db.Column(db.Integer, index=True, default=0) fbliked = db.Column(db.Integer, index=True, default=0) state = db.Column(db.Integer, index=True) email = db.Column(db.String(60)) phonenumber = db.Column(db.String(15)) agerange = db.Column(db.String(15)) 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(JSONEncodedDict(255)) #used for handling extra details site = db.relationship(Wifisite, backref=db.backref("guests", \ cascade="all,delete")) __export_titles__ = [ 'Firstname', 'Lastname', 'Email', 'Phone Number', 'Age Range', "DOB", 'Extra', "Created on" ] __export_public__ = [ 'firstname', 'lastname', 'email', 'phonenumber', 'agerange', 'dob', 'details', 'created_at' ] __export_modifiers__ = { 'created_at': 'format_datetime', 'details': 'guest_details_to_str' } def guest_details_to_str(self, key): '''Convert detatils, which are like extra info collected into a string format''' if self.details: return {key: ','.join('{}:{}'.format(k, v) \ for k,v in sorted(self.details.items()))} else: return {} 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_guest_form(self, form, wifisite): 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.update({form.extra1.label.text: form.extra1.data}) if hasattr(form, 'extra2'): details.update({form.extra2.label.text: form.extra2.data}) self.details = details def populate_from_fb_profile(self, profile, wifisite): self.firstname = profile.get('first_name') self.lastname = profile.get('last_name') self.email = profile.get('email') self.gender = profile.get('gender') age_range = profile.get('age_range') dob = profile.get('birthday') if dob: #convert MM-DD-YYY to DD-MM-YYYY self.dob = arrow.get(dob, 'MM/DD/YYYY').format('DD/MM/YYYY') if age_range: self.agerange = '%s-%s' % (age_range.get( 'min', ''), age_range.get('max', '')) def get_query(self, siteid, startdate, enddate): return Guest.query.filter( and_(Guest.siteid == siteid, Guest.demo == 0, Guest.created_at >= startdate.naive, Guest.created_at <= enddate.naive))
class Loginauth(CRUDMixin, SerializerMixin, db.Model): '''Class to store Loginauth credentials, could be FBLogin,VoucherLogin,EMail,SMS etc All logins should be inherited from this class ''' id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) deviceid = db.Column(db.Integer, db.ForeignKey('device.id')) sessions = db.relationship('Guestsession', backref='loginauth',\ lazy='dynamic') starttime = db.Column(db.DateTime,default=datetime.datetime.utcnow,\ index=True) endtime = db.Column(db.DateTime,default=datetime.datetime.utcnow,\ index=True) last_login_at = db.Column(db.DateTime,default=datetime.datetime.utcnow,\ index=True) #to track last login data_limit = db.Column(db.BigInteger) #in MB time_limit = db.Column(db.Integer, default=60) #in mins speed_ul = db.Column(db.Integer, default=0) speed_dl = db.Column(db.Integer, default=0) state = db.Column(db.Integer, default=LOGINAUTH_INIT) relogin = db.Column(db.Integer, default=0) blocked = db.Column(db.Integer, default=0) site = db.relationship(Wifisite, backref=db.backref("loginauths", cascade="all,delete")) type = db.Column(db.String(50), index=True) __mapper_args__ = { 'polymorphic_identity': 'loginauth', 'polymorphic_on': type } def time_available(self): '''Check validity and return remaining minutes''' if not self.time_limit: #if no limit set return a large value return 480 utcnow = arrow.utcnow() validity = arrow.get(self.starttime).replace(minutes=self.time_limit) availabletime = validity.timestamp - utcnow.timestamp if availabletime > 60: # convert from seconds to mins return int(availabletime / 60) else: return 0 def data_available(self, *args, **kwargs): '''Check validity ''' if not self.data_limit: #if no limit set return a large value return 10000 data_used = 0 sessions = Guestsession.query.filter( and_(Guestsession.siteid == self.siteid, Guestsession.loginauthid == self.id, Guestsession.override == 0, Guestsession.starttime >= self.starttime)).all() for sess in sessions: if sess.data_used: data_used = int(sess.data_used) + data_used data = int(self.data_limit) - data_used if data > 0: return data else: return 0 def get_usage(self, fromtime): '''Check validity ''' data_used = 0 time_used = 0 sessions = Guestsession.query.filter( and_(Guestsession.siteid == self.siteid, Guestsession.loginauthid == self.id, Guestsession.override == 0, Guestsession.starttime >= fromtime)).all() for sess in sessions: if sess.data_used: data_used = int(sess.data_used) + data_used if sess.duration: time_used = int(sess.duration) + time_used return (time_used, data_used) def reset_usage(self, fromtime): '''Reset all sessions from given time to now ''' sessions = Guestsession.query.filter( and_(Guestsession.siteid == self.siteid, Guestsession.loginauthid == self.id, Guestsession.override == 0, Guestsession.starttime >= fromtime)).all() for sess in sessions: sess.override = 1 sess.save() def populate_auth_details(self, modconfig): '''Method to populate session details from modconfig ''' self.data_limit = modconfig.data_limit self.time_limit = modconfig.time_limit self.speed_ul = modconfig.speed_ul self.speed_dl = modconfig.speed_dl self.save() def reset(self): self.starttime = arrow.utcnow().naive self.save() def reset_lastlogin(self): self.last_login_at = arrow.utcnow().naive self.save() def login_completed(self, loginconfig): if self.state == LOGINAUTH_INIT: return False else: return True def is_blocked(self): if self.blocked: return True else: return False def is_currently_active(self): '''check if any of the session is currently on going ''' utcnow = arrow.utcnow().naive if Guestsession.query.filter( and_(Guestsession.loginauthid == self.id, Guestsession.stoptime > utcnow)).count(): return True else: return False def get_query(self, siteid, startdate, enddate): return Loginauth.query.filter( and_(Loginauth.siteid == siteid, Loginauth.starttime >= startdate.naive, Loginauth.starttime <= enddate.naive))
class Landingpage(CRUDMixin, SerializerMixin, db.Model): ''' Class to represent landing page design ''' id = db.Column(db.Integer, primary_key=True) siteid = 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) 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)) #set up cascading to delete automatically site = db.relationship(Wifisite, backref=db.backref("landingpages", cascade="all,delete")) __form_fields_avoid__ = ['id', 'siteid']
class Wifisite(CRUDMixin, SerializerMixin, 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) sitekey = db.Column(db.String(50), index=True, default="default") backend_type = db.Column(db.String(50), default='unifi') template = db.Column(db.String(50), default='default') reports_type = db.Column(db.String(10), default='none') reports_list = db.Column(db.String(400)) redirect_url = db.Column(db.String(200), default='http://www.spotipo.com') timezone = db.Column(db.Text(100), default='UTC') #define special methodfields which will store all the enabled methods preauth_methods = db.Column(JSONEncodedDict(255)) auth_methods = db.Column(JSONEncodedDict(255), default={'auth_email': 1}) postauth_methods = db.Column(JSONEncodedDict(255)) export_methods = db.Column(JSONEncodedDict(255)) #serializer arguement __json_hidden__ = ['default_landing', 'admin_id', 'account_id'] __json_modifiers__ = { 'preauth_methods': 'modeljson_to_dict', 'auth_methods': 'modeljson_to_dict', 'postauth_methods': 'modeljson_to_dict', 'export_methods': 'modeljson_to_dict', } __form_fields_avoid__ = [ 'id', 'default_landing', 'admin_id', 'account_id', 'template' ] __form_fields_modifiers__ = { 'preauth_methods': 'form_to_modeljson', 'auth_methods': 'form_to_modeljson', 'postauth_methods': 'form_to_modeljson', 'export_methods': 'form_to_modeljson', } def get_num_methods(self, methodtype): #get number of configured methods for this method type methods = getattr(self, methodtype) num = 0 if methods: for key, val in methods.iterm(): if val: num = num + 1 else: num = 0 return num def get_methods(self, methodtype): #get all the configured methods for this method type methodslist = [] methods = getattr(self, methodtype) if methods: for key, val in methods.items(): if val: methodslist.append(key) return methodslist def check_login_en(self, ltype): if self.auth_methods: return self.auth_methods.get(ltype) else: return None def check_prelogin_en(self, ltype): if self.preauth_methods: return self.preauth_methods.get(ltype) else: return None def site_from_baseform(self, form): #create self.name = form.name.data self.timezone = form.timezone.data self.client_id = form.client_id.data self.backend_type = form.backend_type.data
class Emailconfig(CRUDMixin,SerializerMixin,db.Model): id = db.Column(db.Integer, primary_key=True) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) enable_fields = db.Column(JSONEncodedDict(255)) mandate_fields = db.Column(JSONEncodedDict(255)) labelfor_fields = db.Column(JSONEncodedDict(255)) data_limit = db.Column(db.BigInteger,default=0) time_limit = db.Column(db.Integer,default=60) speed_ul = db.Column(db.Integer,default=0) speed_dl = db.Column(db.Integer,default=0) session_limit_control= db.Column(db.Integer) session_overridepass = db.Column(db.String(50)) relogin_policy = db.Column(db.String(25),default='onetime') site = db.relationship(Wifisite, backref=db.backref("emailconfigs", \ cascade="all,delete")) def __init__(self): '''Initial values for fields ''' self.enable_fields = {'enable_email': 1, 'enable_firstname':1, 'enable_lastname':1,'enable_dob':0, 'enable_extra1':0,'enable_extra2':0 } self.mandate_fields = {'mandate_email': 1, 'mandate_firstname':1, 'mandate_lastname':1,'mandate_dob':0, 'mandate_extra1':0,'mandate_extra2':0 } self.labelfor_fields = {'labelfor_email': 'Email Address', 'labelfor_firstname':'First Name', 'labelfor_lastname':'Last Name','labelfor_dob':'', 'labelfor_extra1':'','labelfor_extra2':'' } #serializer arguement __json_hidden__ = [] __json_modifiers__ = { 'enable_fields':'modeljson_to_dict', 'mandate_fields':'modeljson_to_dict', 'labelfor_fields':'modeljson_to_dict'} __form_fields_avoid__ = ['id','siteid','account_id'] __form_fields_modifiers__ = { 'enable_fields':'form_to_modeljson', 'mandate_fields':'form_to_modeljson', 'labelfor_fields':'form_to_modeljson', } def is_limited(self): #check if any limits are configured (daily/monthly) if self.session_limit_control: return True else: return False def is_daily_limited(self): if self.session_limit_control == 1: return True else: return False def is_monthly_limited(self): if self.session_limit_control == 2: return True else: return False def get_limit_starttime(self): tzinfo = tz.gettz(self.site.timezone) if self.is_daily_limited(): starttime = arrow.now(tzinfo).floor('day').naive elif self.is_monthly_limited(): starttime = arrow.now(tzinfo).floor('month').naive else: starttime = arrow.utcnow().naive return starttime
class Notification(CRUDMixin, SerializerMixin, 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 ''
class Voucher(CRUDMixin,SerializerMixin,db.Model): id = db.Column(db.Integer, primary_key=True) batchid = db.Column(db.String(10),index=True) voucher = db.Column(db.String(20),index=True,unique=True) notes = db.Column(db.String(50),index=True) duration_type = db.Column(db.Integer,default=1) duration_val = 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) active = db.Column(db.Integer,default=1,index=True) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) used_at = db.Column(db.DateTime,index=True) #used time in UTC,filled once voucher is used site = db.relationship(Wifisite, backref=db.backref("vouchers", \ cascade="all,delete")) __form_fields_avoid__ = ['id','siteid','account_id','voucher', 'used_at','used','active'] def get_duration(self): '''Returns duration in minutes''' if self.duration_type == 1: return self.duration_val elif self.duration_type == 2: return self.duration_val * 60 elif self.duration_type == 3: return self.duration_val * 60 * 24 else: return 0 def get_query(self,siteid,startdate,enddate): return Voucher.query.filter_by(siteid=siteid) def check_and_update_validity(self,loginauth,starttime=None): '''Check if current device can do login ''' if starttime: utcnow = starttime.naive else: utcnow = arrow.utcnow().naive #get currently active auths for this account auths = Voucherauth.query.filter(and_(Voucherauth.voucherid==\ self.id,Voucherauth.endtime > utcnow)).all() devices = [] for auth in auths: if auth.is_currently_active(): devices.append(auth.deviceid) #check if max number of devices are already connected if loginauth.deviceid not in devices and \ len(devices) >= self.num_devices: current_app.logger.warning('Max device limit reached for:%s, not able to login\ device:%s'%(self.id,loginauth.deviceid)) return (None,_('Looks like max allowed devices are already connected')) #check timelimit if voucher is already used if self.used_at: usage = arrow.get(utcnow).timestamp - arrow.get(self.used_at).timestamp duration = self.get_duration()*60 - usage startedat = self.used_at else: duration = self.get_duration()*60 self.used_at = utcnow self.used = True self.save() startedat = utcnow if not duration > 60: current_app.logger.warning('Time limit reached for:%s, not able to login\ device:%s'%(self.id,loginauth.deviceid)) return (None,_('Looks like you have reached max time limit')) time_available = int(math.floor(duration/60)) data_available = 0 if self.bytes_t: # if data limit is specified (time_used,data_used) = loginauth.get_usage(startedat) if not data_used < self.bytes_t: current_app.logger.warning('Max data limit reached for:%s, not able to login\ device:%s'%(self.id,loginauth.deviceid)) return (None,_('Looks like you have reached max data limit')) else: data_available = self.bytes_t - data_used else: data_available = 0 #all good, update login auth and return it loginauth.starttime = utcnow loginauth.time_limit = time_available loginauth.data_limit = data_available loginauth.endtime = arrow.get(utcnow).\ replace(minutes=time_available).naive loginauth.speed_ul = self.speed_ul loginauth.speed_dl = self.speed_dl loginauth.save() return (True,'')