def user_channel_post(channel_name, username): new_user_channel = None try: contact = request.args.get('contact') if contact is None or contact == '': return error_view(400, "invalid contact") channel = Channel.get(channel_name) user = User.get(username) if UserChannel.exists(user.username, channel.name): return error_view(500, "this channel is already linked") new_user_channel = UserChannel.new(user.username, channel.name, contact) new_user_channel.insert() template = CHANNEL_VERIFY_TEMPLATE template.set_format(token=new_user_channel.token, channel=channel.name) send(contact, channel, template) return user_ch_created_view(new_user_channel) except (MailSendingError, TelegramSendingError): if new_user_channel is not None: new_user_channel.delete() return error_view(500, "error sending token to this contact")
def post(): try: body = request.get_json() identity = body.get('identity') password = body.get('password') if identity is None or identity == '' or password is None or password == '': return error_view(400, 'missing parameter') if User.exists_from_email(identity): # assume identity is email user = User.get_from_email(identity) else: # assume identity is username user = User.get(identity) if not user.verify_password(password): return error_view(401, "error logging in") # creating JWT # https://flask-jwt-extended.readthedocs.io/en/stable/basic_usage/ additional_claims = dict(role=user.role) access_token = create_access_token(identity=user.username, additional_claims=additional_claims) return token_view(access_token) except ObjectNotFound: return error_view(404, "error logging in")
def put(domain_name): try: dn = DomainName.get(domain_name) ip_address = dn.resolve() if ip_address is None: return error_view(404, "resolution not found") if not IPAddress.exists(ip_address): # the DN resolves a new address ip = IPAddress.new(ip_address) ip.insert() if not Resolution.exists(domain_name, ip_address): # ip change detected resolution = Resolution.new(domain_name, ip_address) resolution.insert() else: resolution = Resolution.get(domain_name, ip_address) resolution.update() return dn_modified_view(dn) except ObjectNotFound as o: return error_view(404, str(o)) except DomainNameResolutionError as dre: return error_view(500, str(dre))
def post(domain_name): try: if DomainName.exists(domain_name): return error_view(500, f"domain name {domain_name} already exists") dn = DomainName.new(domain_name) dn.insert() ip_address = dn.resolve() # in case resolutions went fine if ip_address is not None: if not IPAddress.exists(ip_address): ip = IPAddress.new(ip_address) ip.insert() resolution = Resolution.new(domain_name, ip_address) resolution.insert() # create user link username = get_jwt_identity() user_dn = UserDn.new(username, dn.domain_name, True) user_dn.insert() return dn_created_view(dn) except DomainNameResolutionError as dre: return error_view(500, str(dre))
def token_check(): token = request.args.get('token') if token is None or token == "": return error_view(400, "missing token") if UserPending.exists(token): return valid_view("valid token") else: return error_view(400, "invalid token")
def user_channel_delete(channel_name, username): try: if channel_name == Channel.DEFAULT: return error_view(500, "cannot unlink default channel") user_channel = UserChannel.get(username, channel_name) user_channel.delete() return user_ch_deleted_view(user_channel) except ObjectNotFound: return error_view(404, "user channel not found")
def put(scheduler_name): if not User.exists(scheduler_name): return error_view(404, "scheduler not found") password = get_password_json() if password is None: return error_view(400, 'invalid parameter') scheduler = User.get(scheduler_name) scheduler.update_password(password) return scheduler_updated_view(scheduler)
def ch_put(name): infos = request.json if infos is None or infos == '': return error_view(400, "missing parameter") if not Channel.exists(name): return error_view(404, f"channel {name} not found") ch = Channel.get(name) ch.update(infos) return ch_admin_put_view(ch)
def ch_delete(name): if name == Channel.DEFAULT: return error_view(403, f"cannot modify default channel") if not Channel.exists(name): return error_view(404, f"channel {name} not found") ch = Channel.get(name) user_channel_list = UserChannel.list_from_channel(ch.name) for user_ch in user_channel_list: user_ch.delete() ch.delete() return ch_admin_delete_view(ch)
def alert_list_export(dn_list: list, export): data = [] for dn in dn_list: data.append([ dn['domain_name'], dn['domain_name_tags'], dn['last_ip_address'], dn['last_ip_tags'], dn['current_ip_address'], dn['current_ip_tags'] ]) columns = [ 'Domain name', 'Domain name tags', 'Last IP address', 'Last IP tags', 'Current IP address', 'Current IP tags' ] df = pandas.DataFrame(data=data, columns=columns) if export == EXPORT_CSV: exported_data = df.to_csv(index=False) mimetype = "text/csv" elif export == EXPORT_JSON: exported_data = df.to_json(orient='split', index=False) mimetype = "application/json" else: return error_view(400, "invalid export field") return Response(exported_data, headers={"Content-Type": mimetype}), 200
def get(domain_name): dn = None dn_tags = [] owned = False followed = False username = get_jwt_identity() try: dn = DomainName.get(domain_name) dn_tags = TagDnIP.list_tags_from_object(dn.domain_name, DOMAIN_NAME_COLLECTION) if not UserDn.exists(username, domain_name): owned = False followed = False else: user_dn = UserDn.get(username, domain_name) owned = user_dn.owned followed = True resolution = Resolution.get_current_from_domain(dn.domain_name) ip = IPAddress.get(resolution.ip_address) ip_tags = TagDnIP.list_tags_from_object(ip.address, IP_ADDRESS_COLLECTION) return dn_retrieved_view(dn, dn_tags, ip, ip_tags, owned, followed) except ObjectNotFound as o: return error_view(404, str(o)) except DomainNameResolutionError: return dn_retrieved_view(dn, dn_tags, None, [], owned, followed)
def post(scheduler_name): if User.exists(scheduler_name): return error_view(500, "name unavailable") password = get_password_json() if password is None: return error_view(400, 'invalid parameter') admin_user = User.get(get_jwt_identity()) new_scheduler = User.new(scheduler_name, password, admin_user.email, is_scheduler=True) new_scheduler.insert() return scheduler_created_view(new_scheduler)
def get_reverse(ip_address): if request.method == 'GET': resolution_list = Resolution.list_from_ip(ip_address) if len(resolution_list) == 0: return error_view(404, "no resolution found for this IP") return dn_resolutions_list_view(resolution_list)
def check_jwt(): if request.method == 'GET': try: token = get_jwt() return valid_view("token is valid") except Exception: return error_view(400, "invalid token")
def get_resolutions(domain_name): if request.method == 'GET': try: # return the list of IPs resolved by this domain name r = Resolution.get_current_from_domain(domain_name) return dn_resolutions_view(r) except DomainNameResolutionError as de: return error_view(404, str(de))
def post(tag_name): if Tag.exists(tag_name): return error_view(500, "tag already exists") new_tag = Tag.new(tag_name) new_tag.insert() return tag_created_view(new_tag)
def remove_user(): username = request.args.get('username') if username is None: return error_view(400, "missing username") user = User.get(username) if user.role != UserRole.ADMIN.value: user.delete() user_channels = UserChannel.list_from_username(user.username) for user_ch in user_channels: user_ch.delete() return user_deleted_view(user) else: return error_view(500, "cannot remove an admin user")
def request_remove(): try: body = request.json if body is None: return error_view(400, "invalid JSON in body") email = body.get('email') if email is None: return error_view(400, "invalid email value") user_request = UserRequest.get(email) user_request.delete() return user_request_deleted_view(user_request) except ObjectNotFound: return error_view(404, "object not found")
def delete(tag, object_key, object_type): if not TagDnIP.exists(tag, object_key, object_type): return error_view(404, "tag link not found") tag_link = TagDnIP.get(tag, object_key, object_type) tag_link.delete() return tag_link_deleted_view(tag_link)
def user_channel_put(channel_name, username): try: token = request.args.get('token') if token is None or token == '': return error_view(400, 'missing token') user_channel = UserChannel.get(username, channel_name) if user_channel.verified: return error_view(500, 'this channel has already been verified') if token != user_channel.token: return error_view(500, 'invalid token') user_channel.update(verified=True) return user_ch_updated_view(user_channel) except ObjectNotFound: return error_view(404, "user channel not found")
def get_list(): try: username = get_jwt_identity() input_filter = request.args.get('filter') input_filter_by = request.args.get('filter_by') sort_by = request.args.get('sort_by') limit_str = request.args.get('limit') days_str = request.args.get('days') export = request.args.get('export') params = [input_filter, input_filter_by, sort_by, limit_str, days_str] for p in params: if p is None: return error_view(400, 'missing parameter') if not limit_str.isdigit(): return error_view(400, 'invalid limit') if not days_str.isdigit(): return error_view(400, 'invalid days count') limit = int(limit_str) days = int(days_str) t1 = time() dn_list = DomainName.list_recent_changes( username, days, input_filter, input_filter_by, sort_by, limit ) t2 = time() transaction_time = round(t2 - t1, 2) if export is not None and export != '': return alert_list_export(dn_list, export) else: return alert_list(dn_list, transaction_time) except DomainNameFilterNotFound: return error_view(400, "invalid filter field") except DomainNameSortNotFound: return error_view(400, "invalid sort field")
def manage_domain_name_list(): if request.method == 'GET': try: username = get_jwt_identity() input_filter = request.args.get('filter') input_filter_by = request.args.get('filter_by') sort_by = request.args.get('sort_by') limit_str = request.args.get('limit') export = request.args.get('export') owned_filter = request.args.get('owned') is not None followed_filter = request.args.get('followed') is not None params = [input_filter, input_filter_by, sort_by, limit_str] for p in params: if p is None: return error_view(400, 'missing parameter') if not limit_str.isdigit(): return error_view(400, 'invalid limit') limit = int(limit_str) t1 = time() dn_list = DomainName.list(username, input_filter, input_filter_by, owned_filter, followed_filter, sort_by, limit) t2 = time() transaction_time = round(t2 - t1, 2) if export is not None and export != '': # export file data return dn_list_export(dn_list, export) else: # export json data return dn_list_view(dn_list, transaction_time) except DomainNameFilterNotFound: return error_view(400, "invalid filter field") except DomainNameSortNotFound: return error_view(400, "invalid sort field")
def manage_follow(domain_name): domain_name = refang(domain_name) username = get_jwt_identity() if request.method == 'POST': if UserDn.exists(username, domain_name): return error_view(500, "you are already following this DN") user_dn = UserDn.new(username, domain_name, False) user_dn.insert() return valid_view("DN added to your follows") elif request.method == 'DELETE': if not UserDn.exists(username, domain_name): return error_view(404, "you are not following thiS DN") user_dn = UserDn.get(username, domain_name) user_dn.delete() return valid_view("DN removed from your follows")
def channel_test(channel_name): try: username = get_jwt_identity() if request.method == 'GET': user = User.get(username) channel = Channel.get(channel_name) user_channel = UserChannel.get(user.username, channel.name) template = TEST_TEMPLATE template.set_format(date=str(datetime.now().date())) send(user_channel.contact, channel, template) return user_ch_test_view(user_channel) except ObjectNotFound: return error_view(404, "object not found") except (MailSendingError, TelegramSendingError): return error_view(500, "failed to send test")
def manage_tag_dn_ip_list(): object_key = request.args.get('object') object_type = request.args.get('type') params = [object_key, object_type] for p in params: if p is None or p == '': return error_view(400, "invalid parameter") tag_linked_list = TagDnIP.list_tags_from_object(object_key, object_type) return tag_link_list_view(tag_linked_list)
def delete(domain_name): try: username = get_jwt_identity() if not UserDn.exists(username, domain_name): return error_view(403, "no ownership found") # remove ownership user_dn = UserDn.get(username, domain_name) if not user_dn.owned: return error_view(403, "you do not own this domain") user_dn.delete() # remove tags dn_linked_tags = TagDnIP.list_tags_from_object(domain_name, DOMAIN_NAME_COLLECTION) for t in dn_linked_tags: t.delete() # remove resolution / IP resolution_list = Resolution.list_from_domain(domain_name) for r in resolution_list: r.delete() ip_address = r.ip_address res_ip_list = Resolution.list_from_ip(ip_address) if len(res_ip_list) == 0: ip_linked_tags = TagDnIP.list_tags_from_object( ip_address, IP_ADDRESS_COLLECTION) for t in ip_linked_tags: t.delete() ip = IPAddress.get(ip_address) ip.delete() dn = DomainName.get(domain_name) dn.delete() return dn_deleted_view(dn) except ObjectNotFound as o: return error_view(404, str(o))
def delete(tag_name): if not Tag.exists(tag_name): return error_view(404, "tag not found") tag = Tag.get(tag_name) tag.delete() tag_links = TagDnIP.list_from_tag(tag.name) for t in tag_links: t.delete() return tag_deleted_view(tag)
def post(tag_name, object_key, object_type): if TagDnIP.exists(tag_name, object_key, object_type): return error_view(500, "tag link already exists") if not Tag.exists(tag_name): return error_view(404, "source tag not found") if object_type == DOMAIN_NAME_COLLECTION: object_exists = DomainName.exists(object_key) elif object_type == IP_ADDRESS_COLLECTION: object_exists = IPAddress.exists(object_key) else: return error_view(400, "invalid object type") if not object_exists: return error_view(404, "target object not found") new_tag_link = TagDnIP.new(tag_name, object_key, object_type) new_tag_link.insert() return tag_link_created_view(new_tag_link)
def request_access(): body = request.json if body is None: return error_view(400, "invalid JSON in body") email = body.get('email') if email is None: return error_view(400, "invalid email value") if User.exists_from_email(email): return error_view(500, "email unavailable") if UserPending.exists_from_email(email): return error_view(500, "an invitation has already been sent to this email") if UserRequest.exists(email): return error_view(500, "a request for this email has already been sent") user_request = UserRequest.new(email) user_request.insert() return user_request_created_view(user_request)
def ch_post(name): try: ch_type = request.args.get('type') if ch_type is None or ch_type == '': return error_view(400, "missing parameter") infos = request.json if infos is None or infos == '': return error_view(400, "missing json") if Channel.exists(name): return error_view(500, "a channel with this name already exists") new_ch = Channel.new(name, ch_type, infos) new_ch.insert() return ch_admin_post_view(new_ch) except KeyError: return error_view(500, "error parsing json input") except ChannelTypeError: return error_view(400, "invalid channel type")