def new_beer_call(self, id_group, data): try: title = data.get('title') text = data.get('message') new_beer_call = datetime.now() last_beer_call = datetime.strptime(self.get_global(id_group).get('beer_call'), '%m-%d-%Y %H:%M:%S') if last_beer_call: time_diff = new_beer_call - last_beer_call if time_diff.seconds < 3600: return Error('Not allowed to send notification, delay not great', 403).get_error() new_beer_call = new_beer_call.strftime('%Y-%m-%d %H:%M:%S') with self.con: cur = self.con.cursor(Model = UserGroup) sql = "UPDATE `groups` SET `beer_call` = %s WHERE id = %s" cur.execute(sql, (new_beer_call, id_group)) self.con.commit() list_users = self.list_user_from_group(id_group) login_list = [] for nb, user in list_users.items(): login_list.append(user.get('login')) tokens = UserView().list_tokens_from_logins(login_list) message = NotificationMessage({'title': title, 'text': text}) NotificationsView(message, tokens).send_push_message() return self.get(id_group) except Exception as e: print(e) self.con.rollback() return Error('Problem happened in updating user beer call in group', 400).get_error()
def delete(self, id_group, login): try: with self.con: cur = self.con.cursor(Model = Group) sql = "SELECT * FROM `groups` WHERE id=%s" cur.execute(sql, id_group) group = cur.fetchone() if group is None: return Error('Not Found', 404).get_error() if group.to_json()['owner'] == login: sql = "DELETE FROM `groups` WHERE id = %s AND owner=%s" cur.execute(sql, (id_group, login)) if cur.rowcount == 0: return Error('User unauthorized to delete this group', 403).get_error() self.con.commit() else: return self.remove_from_group(id_group, login) return self.list(login) except Exception as e: print(e) self.con.rollback() return Error('Problem happened in group deletion', 400).get_error()
def update_group(id, user=None): """Update a group""" try: data = json.loads(request.body.read()) login = user.to_json().get('login') if data.get('invitation'): invitation_type = data.get('invitation') return GroupView().handle_invitation(id, login, invitation_type) if data.get('beer_call'): return GroupView().new_beer_call(id) if data.get('location_permission'): permission = bool(data.get('location_permission')) return GroupView().update_permission_location(id, login, permission) if data.get('location_sent'): try: location = Location(data.get('location_sent')) except Error as e: return Error('Wrong location attribute', 400) if GroupView().user_allow_location(id, user.to_json().get('login')): return GroupView().update_location(user.to_json().get('login'), location, id) else: return Error('User do not allow location', 403) except Exception as e: return e
def wrapper(*args, **kwargs): auth = request.headers.get('Authorization') if auth is None: return Error('Not Logged', 401).get_error() user = AuthTokenView().get(auth) if isinstance(user, dict): return user if not user.to_json()['isAdmin']: return Error('Not Admin', 403).get_error() return f(user=user, *args, **kwargs)
def autocomplete(self, query): try: with self.con: decoded_query = unquote(query) decoded_query = decoded_query.split(' ') words = [] for word in decoded_query: if len(word): words.append(word) if not len(words): return {} words = '|'.join(words) cur = self.con.cursor(Model= User) sql = "SELECT login, firstname, lastname, img_url, img_width, img_height FROM users_app WHERE login REGEXP %s OR firstname REGEXP %s OR lastname REGEXP%s LIMIT 5" cur.execute(sql, (words, words,words)) list_users = cur.fetchall() print(list_users) result = {} count = 0 for user in list_users: result[count] = user.to_json() count +=1 return result except Exception as e: print(e) response.status = 400 return Error('Problem happened in query list', 501).get_error()
def list(self, list=None, mail=None): with self.con: try: cur = self.con.cursor(Model = User) if list is not None: t = tuple(list) lookup = f"IN {t}" if len(t) > 1 else f"='{t[0]}'" sql = "Select login, lastname, firstname, email, password, isAdmin, ST_X(lastPosition) AS latitude, " \ f"ST_Y(lastPosition) AS longitude, push_token, img_url, img_width, img_height from users_app WHERE login {lookup}" else: sql = "Select login, lastname, firstname, email, password, isAdmin, ST_X(lastPosition) AS latitude, " \ "ST_Y(lastPosition) AS longitude, push_token, img_url, img_width, img_height from users_app" cur.execute(sql) users = cur.fetchall() users_dict = {} count = 0 for user in users: users_dict[count] = user.to_json() count += 1 return users_dict except Exception as e: print(e) response.status = 400 return Error('Problem happened in query list').get_error()
def reset_password(self): """ generate a new password for the login and send it by mail """ letters = string.ascii_lowercase new_pwd = ''.join(random.choice(letters) for i in range(10)) try: with self.con: cur = self.con.cursor(Model = User) sql = "UPDATE users_app SET password=aes_encrypt(%s, %s) WHERE login=%s;" cur.execute(sql, (new_pwd, SALT, self.login)) self.con.commit() email = self.get(self.login).to_json().get('email') msg = """ Salut, participant.e à l'édition 2020 de SKI'UTC. Comme tu as pu le constater, cette année, <br> De la nouveauté cette année : une application SKI'UTC rien que pour toi, rien que pour vous ! <br> <br> Cours l'installer sur le store de ton téléphone (recherches SKI'UTC) <br> <br> Pour te connecter c'est simple : tu utilises ton login (ou email si tu es tremplin), et tu utilises ces codes : <br><br> <B>IDENTIFIANT : {}</B><br> <B>PASSWORD : {}</B><br> """.format(self.login, new_pwd) Mail().mail_sender(email, "Ton mot de passe pour l'application SKI'UTC", msg) return new_pwd except Exception as e: print(e) self.con.rollback() response.status = 400 return Error('Error happened in password reset process').get_error()
def bot_account_verification(self, pwd): """ check the login and pwd given to authenticate user save en give a token """ try: with self.con: cur = self.con.cursor(Model = User) sql = "SELECT login, lastname, firstname, password FROM users_app WHERE login=%s and password=aes_encrypt(%s, %s)" cur.execute(sql, (self.login, pwd, SALT)) user = cur.fetchone() if user is None: return None return user.to_json() except Error as e: return e.get_error() except Exception as e: print(e) response.status = 400 return Error('Authentication error').get_error() finally: cur.close() self.con.close()
def push_token(self, push_token): try: with self.con: try: cur = self.con.cursor(Model=User) sql = "UPDATE users_app SET `push_token`=%s WHERE login=%s" cur.execute(sql, (push_token, self.login)) self.con.commit() except Exception as e: self.con.rollback() raise e sql = "SELECT login, lastname, firstname, email, password, isAdmin, ST_X(lastPosition), " \ "ST_Y(lastPosition), push_token FROM users_app WHERE login=%s" cur.execute(sql, self.login) user = cur.fetchone() return user.to_json() except Error as e: return e.get_error() except Exception as e: response.status = 501 return Error('Problem happened in adding push token', 501).get_error() finally: self.con.close()
def create(self, data): try: with self.con: title = data.get('title') text = data.get('text') img_url = data.get('img_url') img_width = data.get('img_width') img_height = data.get('img_height') type = data.get('type') cur = self.con.cursor(Model=News) sql = "INSERT INTO news (title, text, img_url, img_width, img_height, date, type) VALUES (%s, %s, %s, %s, %s, %s, %s)" now = datetime.now() now = now.strftime('%Y-%m-%d %H:%M:%S') cur.execute( sql, (title, text, img_url, img_width, img_height, now, type)) self.con.commit() sql = "SELECT * FROM news WHERE id = (SELECT MAX(id) FROM news)" cur.execute(sql) last = cur.fetchone() tokens = UserView().list_tokens() message = NotificationMessage(data) NotificationsView(message, tokens).send_push_message() if type == 'email': list_mail = UserView().list_mail() Mail().massive_mail_sender(list_mail, title, text) return last.to_json() except Exception as e: print(e) self.con.rollback() return Error('Problem happened in news creation', 400).get_error()
def handle_invitation(self, id_group, login, invitation_type): try: if invitation_type == 'V': with self.con: cur = self.con.cursor(Model = UserGroup) sql = "UPDATE `usergroup` SET status = 'V' WHERE `id_group` = %s AND `login_user` = %s" cur.execute(sql, (id_group, login)) self.con.commit() group = self.get_global(id_group) group['user_status'] = 'V' return self.list(login) else: with self.con: cur = self.con.cursor(Model=UserGroup) sql = "DELETE FROM `usergroup` WHERE `id_group` = %s AND `login_user` = %s" cur.execute(sql, (id_group, login)) self.con.commit() return self.list(login) except Exception as e: print(e) self.con.rollback() return Error('Problem happened in updating user status in group', 400).get_error()
def list_user_from_group(self, id_group, accept_only=False): try: with self.con: cur = self.con.cursor(Model = UserGroup) accept_sql = f"AND `status`= 'V'" if accept_only else "" sql = f"SELECT * from `usergroup` WHERE `id_group` = %s {accept_sql}" cur.execute(sql, id_group) users_group = cur.fetchall() ug_dict = {} login_list = [] for user in users_group: user = user.to_json() ug_dict[user['login_user']] = user login_list.append(user['login_user']) users = UserView().list(list=login_list) for user_key in users: user = users[user_key] user_group = ug_dict.get(user['login']) user['status'] = user_group['status'] user['expiration_date'] = user_group['expiration_date'] if user_group['share_position']: user['location'] = UserView(user['login']).get_location() users[user_key] = user return users except Exception as e: print(e) return Error('Problem happened in query list', 400).get_error()
def rm_sys_disk(self, raise_exception=False): """ 删除系统盘,需要先删除所有系统盘快照 :param raise_exception: 删除错误时是否抛出错误 :return: True # success False # failed :raises: Error # When raise_exception == True """ if not self.disk: return True config = self.get_ceph_cluster() if not config: return False try: remove_image(ceph=config, pool_name=self.ceph_pool, image_name=self.disk) except Error as e: if raise_exception: raise Error(msg=str(e)) return False self.disk = '' try: self.save(update_fields=['disk']) except Exception as e: pass return True
def get(self, token): """ return the auth token if exist """ with self.con: try: cur = self.con.cursor(Model=AuthToken) sql = "SELECT * FROM auth_token WHERE token=%s" cur.execute(sql, token) authentication = cur.fetchone() if authentication is None: raise Error('Not logged', 403) authentication = authentication.to_json() user = UserView(authentication['login']).get() return user except Error as e: return e.get_error() except Exception as e: return e
def list(self, admin=False): try: with self.con: cur = self.con.cursor(Model=Potin) if admin: sql = "SELECT * from potin WHERE approved = 0 ORDER BY id DESC" else: sql = "SELECT * from potin WHERE approved = 1 ORDER BY id DESC" cur.execute(sql) response = cur.fetchall() count = 0 result = {} for value in response: potin = value.to_json() #check if anonymous if potin.get('isAnonymous'): potin['sender'] = None result[count] = potin count += 1 return result except Exception as e: print(e) return Error('Problem happen in query list').get_error()
async def import_(client: Client, db: Database, msg: Message) -> KanTeXDocument: """Import a CSV to the banlist. The CSV file should end in .csv and have a `id` and `reason` column Examples: {cmd} """ if msg.is_reply: # pylint: disable = R1702 reply_msg: Message = await msg.get_reply_message() if reply_msg.document: _, ext = os.path.splitext( reply_msg.document.attributes[0].file_name) if ext == '.csv': data = await reply_msg.download_media(bytes) start_time = time.time() _banlist = await helpers.rose_csv_to_dict(data) if _banlist: await db.banlist.upsert_multiple(_banlist) if client.sw and client.sw.permission in [ Permission.Admin, Permission.Root ]: bans = {} for b in _banlist: bans[b['reason']] = bans.get(b['reason'], []) + [b['id']] admin_id = (await client.get_me()).id for reason, uids in bans.items(): uids_copy = uids[:] while uids_copy: client.sw.add_bans([ Ban(int(uid), reason, admin_id) for uid in uids_copy[:SWAPI_SLICE_LENGTH] ]) uids_copy = uids_copy[SWAPI_SLICE_LENGTH:] stop_time = time.time() - start_time return KanTeXDocument( Section('Import Result', f'Added {len(_banlist)} entries.'), Italic(f'Took {stop_time:.02f}s')) else: raise Error('File is not a CSV') else: raise Error('Need to reply to a document')
def delete(self, id_group, login): try: with self.con: cur = self.con.cursor(Model=Group) sql = "DELETE FROM `groups` WHERE id = %s AND owner=%s" cur.execute(sql, (id_group, login)) if cur.rowcount == 0: return Error('User unauthorized to delete this group', 403).get_error() self.con.commit() return self.list(login) except Exception as e: print(e) self.con.rollback() return Error('Problem happened in group deletion', 400).get_error()
def verify_token(self, token, challenge): try: if token == WEBHOOK_TOKEN: return challenge raise Error("Bad token.", 400) except Exception as e: print(e) return e.get_error()
async def query(args, kwargs, db: Database) -> KanTeXDocument: """Query a blacklist for a specific code. Blacklist names are _not_ the hexadecimal short hands Arguments: `type`: One of the possible autobahn types (See {prefix}ab) `code`: The index of the item, can be a range `-retired`: Show retired items Examples: {cmd} domain 3 {cmd} channel 4..20 {cmd} channel """ item_type = kwargs.get('type') code = kwargs.get('code') if item_type is None and args: item_type = args[0] else: raise Error('No blacklist name specified') if code is None and len(args) > 1: code = args[1] hex_type = None blacklist = None if item_type is not None: hex_type = AUTOBAHN_TYPES.get(item_type, item_type) blacklist = await db.blacklists.get(hex_type) blacklist_items = await blacklist.get_all() if code is not None: if isinstance(code, int): code = [code] all_items = await blacklist.get_indices(list(code)[:MAX_QUERY_ITEMS]) else: all_items = blacklist_items retired = kwargs.get('retired', len(all_items) == 1) if not retired: all_items = [i for i in all_items if not i.retired] items = [] for item in all_items[:MAX_QUERY_ITEMS]: kvitem = KeyValueItem( item.index, f"{Code(item.value)} {Italic('(retired)') if item.retired else ''}" ) items.append(kvitem) return KanTeXDocument( Section(f'Items for type: {item_type}[{hex_type}]', *items or [Italic('None')]), Italic(f'Total count: {len(blacklist_items)}') if blacklist_items else None)
def create_news(user=None): """create a news""" try: data = json.loads(request.body.read()) if not data.get('title') or not data.get('text'): return Error('Title or text empty', 400).get_error() return NewsView().create(data) except Exception as e: return e
async def importjustasic_(client: Client, db: Database, msg: Message, chat: Channel, args, kwargs) -> KanTeXDocument: """Import a CSV to the banlist. Made to import a fuckming printed python list who even does this Examples: {cmd} """ reasontoban = kwargs.get('reason') if msg.is_reply: # pylint: disable = R1702 reply_msg: Message = await msg.get_reply_message() if not reply_msg.document: raise Error('Need to reply to a document') _, ext = os.path.splitext(reply_msg.document.attributes[0].file_name) if ext != '.txt': raise Error('File is not a txxxt') data = await reply_msg.download_media(bytes) start_time = time.time() _banlist = await helpers.id_csv_to_dict(data) if _banlist: progress_message: Message = await client.send_message( chat, f"Processing {len(_banlist)} User IDs") while _banlist: uid_batch = _banlist[:CHUNK_SIZE] for uid in uid_batch: await client.ungban(uid) _banlist = _banlist[CHUNK_SIZE:] if _banlist: if progress_message: await progress_message.edit( f"Sleeping for 10 seconds after banning {len(uid_batch)} Users. {len(_banlist)} Users left." ) await asyncio.sleep(10) stop_time = time.time() - start_time return KanTeXDocument( Section('Import Result', f'Added {len(_banlist)} entries.'), Italic(f'Took {stop_time:.02f}s'))
def send_invitation(id, user=None): """send invitation to user/s for a group""" try: data = json.loads(request.body.read()) if not data.get('list_login'): return Error('No login provided - invitation is cancelled', 400) login_list = data.get('list_login') return GroupView().add_to_group(id, login_list=login_list) except Exception as e: return e
def verification(): try: data = request.query verify_token = data.get('hub.verify_token') challenge = data.get('hub.challenge') if challenge is None or verify_token is None: return Error('No data', 400) return BotView().verify_token(verify_token, challenge) except Exception as e: return e
def authenticate(self, pwd): """ check the login and pwd given to authenticate user save en give a token """ try: with self.con: cur = self.con.cursor(Model = User) sql = "SELECT login, lastname, firstname, email, password, isAdmin, ST_X(lastPosition) AS latitude, " \ "ST_Y(lastPosition) as longitude, push_token, img_url, img_width, img_height FROM users_app WHERE login=%s and password=aes_encrypt(%s, %s)" cur.execute(sql, (self.login, pwd, SALT)) user = cur.fetchone() if user is None: raise Error('Authentication error', 400) token = secrets.token_hex(25) try: sql = "DELETE FROM auth_token WHERE login=%s" cur.execute(sql, self.login) sql = "INSERT INTO auth_token (login, token) VALUES (%s, %s)" cur.execute(sql, (self.login, token)) self.con.commit() json_user = user.to_json() json_user['push_token'] = user.get_push_token() return {'user': json_user, 'token': token} except Exception as e: self.con.rollback() raise Error('Authentication error', 400) except Error as e: return e.get_error() except Exception as e: print(e) response.status = 400 return Error('Authentication error').get_error() finally: cur.close() self.con.close()
def authentication(): """authenticate user""" try: data = json.loads(request.body.read()) login = data.get('login') password = data.get('password') if not login or not password: return Error('Login or Password empty', 400).get_error() return UserView(login).authenticate(password) except Exception as e: return e
def create_bot_message(user=None): try: data = json.loads(request.body.read()) text = data.get('text') type = data.get('type', 'text') if not text: return Error('no data', 400).get_error() return BotView().add_message(text, type) except Exception as e: return e
def get_top_users(self): if not self.admin: return Error('Not admin', 403).get_error() result = {} count = 0 try: cur = self.con.cursor(Model=AnimationUser) sql = "SELECT * from `piste_anim` ORDER BY `level` DESC LIMIT 10" cur.execute(sql) response = cur.fetchall() if response is None: return {} for u in response: current = u.to_json() result[count] = current count += 1 return result except Exception as e: print(e) return Error('Problem happened in query get', 400).get_error()
def add_to_group(self, id_group, login_list=None, owner=None, group=None): result = {} count = 0 try: with self.con: if group is None: group = self.get_global(id_group) if owner: cur = self.con.cursor(Model=UserGroup) sql = "INSERT INTO `usergroup` (`login_user`, `id_group`, `status`) VALUES (%s, %s, %s)" cur.execute(sql, (owner, id_group, 'V')) sql = "SELECT * FROM `usergroup` WHERE `id_group` = %s AND `login_user` = %s " cur.execute(sql, (id_group, owner)) last = cur.fetchone() result[count] = last.to_json() count += 1 if login_list: for login in login_list: try: cur = self.con.cursor(Model=UserGroup) sql = "INSERT INTO `usergroup` (`login_user`, `id_group`) VALUES (%s, %s)" cur.execute(sql, (login, id_group)) sql = "SELECT * FROM `usergroup` WHERE `id_group` = %s AND `login_user` = %s" cur.execute(sql, (id_group, login)) last = cur.fetchone() result[count] = last.to_json() count += 1 except Exception as e: print(e) code, message = e.args if code == pymysql.constants.ER.DUP_ENTRY: result[count] = {'error': message} count += 1 else: self.con.rollback() raise e tokens = UserView().list_tokens_from_logins(login_list) message = NotificationMessage({ 'title': 'Invitation de groupe - {}'.format(group.get('name')), 'text': '{} t\'a invité à rejoindre son nouveau groupe !'.format(group.get('owner')) }) NotificationsView(message, tokens).send_push_message() except Exception as e: print(e) return Error('Problem happened when adding to group', 400).get_error() return result
def create_potin(user=None): """create a potin""" try: data = json.loads(request.body.read()) data["approved"] = False data["sender"] = user.to_json().get("login") if not data.get('title') or not data.get('text'): return Error('Title or text empty', 400).get_error() return PotinView().create(data) except Exception as e: return e
def create_group(user=None): """création d'un groupe""" try: data = json.loads(request.body.read()) if not data.get('name'): return Error('Please provide a name', 400) name = data.get('name') owner = user.to_json().get('login') list_login = data.get('list_login') return GroupView(owner).create(name, owner, list_login) except Exception as e: return e