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 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 Voucherconfig(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)) site = db.relationship(Wifisite, backref=db.backref("voucherconfigs", \ 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 Sitestat(CRUDMixin, SerializerMixin, db.Model): ''' Class to represent daily statistics ''' id = db.Column(db.Integer, primary_key=True) siteid = db.Column(db.Integer, db.ForeignKey('wifisite.id')) account_id = db.Column(db.Integer, db.ForeignKey('account.id')) date = db.Column(db.DateTime, index=True) #used as key login_stat = db.Column(JSONEncodedDict(255)) # to hold individual stats num_visits = db.Column(db.Integer, default=0) num_newlogins = db.Column(db.Integer, default=0) num_repeats = 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) #set up cascading to delete automatically site = db.relationship(Wifisite, backref=db.backref("sitestats", cascade="all,delete")) def json_to_dict(self, field_name): '''used for updating dict representation with values for login_stat ''' return getattr(self, field_name) or {} __json_hidden__ = [ 'admin_id', 'account_id', 'avg_time', 'avg_data', 'last_updated', 'date' ] __json_modifiers__ = {'login_stat': json_to_dict} def get_total_logins(self): '''returns total logins for the day ''' return self.num_newlogins + self.num_repeats
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 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 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 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