Giter VIP home page Giter VIP logo

numbersearch's Introduction

CodeQL .NET Build Status

NumberSearch

NumberSearch is the website for AccelerateNetworks a Seattle-area communication services company. ☎

Try it out here!

NumberSearch.Mvc contains a session-based shopping cart and ecommerce system to enable customers to submit orders for products, services, and phone numbers. The number searching tool allows you to purchase a phone number and queries a PostgreSQL database hosted locally alongside the Mvc app to maximize performance. The Ingest app pulls between 300 thousand and a million purchasable phone numbers a day from a half dozen upstream VOIP carriers. The most popular area codes are refreshed every 15 minutes.

Porting is the process of moving a phone number from one carrier to another. When customers switch their VOIP service to Accelerate Networks they often choose to retain their existing phone numbers by using the porting process. The bulk phone number porting tool allows enterprise customers to move hundreds of numbers over to our network in a single order. It also verifies the current carrier and caller Id records to help our customers make sure that they are bringing over the phone numbers that intended too.

The Ops app is an administrative tool for processing orders submitted through the Mvc app and handling line of business task like registering phone number for E911 service, completing port requests, and managing the hardware inventory deployed onsite to customers.

There are three supporting libraries: Tests, DataAccess, and FirstCom. Tests is where all our unit, integration, and functional tests are written. The tests verify that our code can correctly and consistently interact with our vendors and 3rd party dependencies. The DataAccess library is a set of data models and SQL queries for interacting with the PostgreSQL database that is shared between the Mvc, Ops, and Ingest apps. Finally the FirstCom library exists to isolate the autogenerated code required to interact with a vendor’s SOAP API endpoints. 👀

The Messaging project is a prototype Web API that is intended to abstract our upstream SMS/MMS carriers from our internal services.

Architecture

NumberSearch drawio (6)

Run locally on Windows 11

  • Install Visual Studio 2022 Community Edition.
  • Open Visual Studio 2022 (VS2022).
  • Select the "Clone or check out code" option under "Getting Started" on the project selection splash screen.
  • Login to Github if required.
  • Clone this repo from the Master branch.
  • With the project directory now open in VS2022 click the "NumberSearch.sln" file to configure Visual Studio.
  • At the top center of the VS2022 window there is a button with a green arrow labelled "IIS Express" this will run the project on a local web server.
  • Make sure that NumberSearch.Mvc is the currently selected project.

Add configuration keys locally

  • In the VS 2022 menu bar click "Tools" > "NuGet Package Manager" > "Package Manager Console"
  • Run this command to setup a local secrets store "dotnet user-secrets init --project .\NumberSearch.Mvc".
  • Then run this command "dotnet user-secrets init --project .\NumberSearch.Tests".
  • More info and troubleshooting details on configuring user-secrets.

Run on a Debian Server

Install .Net Core SDK, navigate to the project folder and run dotnet publish --configuration Release

Number Import

Create a cronjob using crontab -e to run the ingest:

23 1 * * *  /usr/bin/dotnet /var/www/numberSearch.Ingest/NumberSearch.Ingest.dll >> /var/log/NumberSearchIngest.log 2>&1

Run as a service

Move numbersearch.service to the correct directory, enable it and start the process:

cp numbersearch.service /etc/systemd/system/numbersearch.service
chmod 644 /etc/systemd/system/numbersearch.service
systemctl daemon-reload
systemctl enable numbersearch.service
systemctl start numbersearch.service

Continuous Integration and Deployment

Check out our Azure DevOps pipelines.

numbersearch's People

Contributors

andrewstiefel avatar chattaeus avatar danry25 avatar dunkeltron avatar piajesse avatar uncheckederror avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

wing-888

numbersearch's Issues

Integration test for the FirstCom API is failing

This worked 2 weeks ago, but now it fails to return any result with the error message: "Invalid Webservice Authentication"

But the auth credentials are the same and I verified that the credentials work in the soapclient.com client.

Strip leading 1 when number is over 10 digits long

We should strip the leading 1 from a number that is over 10 digits long. It sounds like we already strip all non-alphanumeric characters, then we convert all non-numeric characters to letters based on our conversation earlier.

Add App Insights to Capture Telemetry

We need to know what request are failing and our users are doing with NumberSearch. App Insights is an Azure service that will handle all of this for us.

Update the BulkVS ingest process to use Custom XML Parsing

Right now we're using a hacked up version of the tools in the framework's XMLSerialization library to ingest data from BulkVS. But it was designed to consume SOAP services built on the framework, so it doesn't work well with the BulkVS SOAP API and its variable response format. We can improve the reliability of this process by using the framework only to capture the raw XML and then writing a custom parser to complete the process of ingesting the data and serializing this XML into native C# objects.

Endstream DID search support

Endstream does have a slow, SOAP API, but the numbers they have available through it can be found nowhere else.

Validate upstream carrier has a number when search occurs

We should check that a number is still available for purchase when we display available numbers to end users if we have not verified the number is available in the last 15 minutes.

Thinking we can expose a loading spinner while these numbers are verified as available, then use javascript to hide the numbers that are not available? That way we are not bottlenecking page load on these queries.

Should we just re-import the NPANXXes that our initial database query returns?

Teli (3 to 6 second response time):
https://apiv1.teleapi.net/dids/list?token=< ourtoken >&search=< npanxx >

FirstCom (400ms to 600ms response time):
Use the DIDInventorySearch endpoint to re-import the NPA-NXX

BulkVS:
Likely this method?

Fix BulkVS SOAP API Error Handling

When the BUlkVS API responds with an error we treat it as an exception because it can't be serialized to the C# object that models the success response. Rather than throwing an exception we can expand the object that the XML response is being de-serialized to by including the fields in the error response. These failure fields would go unused for successful responses and the reverse would be true for failure responses.

Scrape Vendor APIs for Available Numbers

@danry25 Right now the limitation on speed is due to the latency of the TeleAPI that this application is dependent on.

Ideally we would scrape all of the data required for this app once a day from the TeleAPI and then cache it in a database like SQLite or PostgreSQL so that we can control performance.

Originally posted by @uncheckederror in #7 (comment)

Label numbers when ordering through Teli

For Teli can we set the note to be the customer's business name followed by the person who placed the order's name, eg: Accelerate Networks - Dan Ryan - Ordered via API

This is the API to set notes on Teli, sadly BulkVS and Endstream do not support labeling DIDs, hence issue #40 to allow manual reconciliation of owned DIDs on each vendor.

Add additional hardware

Could we add the following phones to the hardware page?

  • Polycom Soundstation IP 7000 ($300ea, picture)
    • Description: Light up your conference room with the vibrant sound quality provided by the Polycom Soundstation IP 7000! Supports 3 way calling, HD Voice & Power over Ethernet.
  • Snom PA1 ($150ea, picture)
    • Description: Enable paging over speaker systems with the Snom PA1. The built in amp enables small scale deployments, while the numerous outputs can tie into existing amplifiers.
  • Split GRP2612 listing, remove WiFi from GRP2612 description and create the GRP2612W ($85ea)
    • Description: Need a phone where only WiFi exists? The GRP2612W has you covered with powerful WiFi 5 (aka 802.11AC) support built in. Plug into power and dial away!

If the flavor text could be massaged so that this new row has a consistent line count that would be ideal.

Add a graph to the Ingests page

While the card format is useful for reviewing the ingests, a graph of the ingest results would be more useful. Perhaps we could have a graph of the past 2 weeks of ingests as the head for this page and then a simple, dense table of ingests below it for more detailed information.

Integrate with Flowroute as a vendor?

They seem to have a decent REST API, and their available numbers do not overlap with our other vendors and appear quite plentiful (eg: over 2600 available numbers in the 206 area code, 26200 available numbers in area codes 226 and below, estimated 484,000 available numbers).

API endpoint to use is https://api.flowroute.com/v2/numbers/available?starts_with=227&limit=200&offset=0 where starts_with is the NPA and offset should be adjusted in increments of 200 to get the next 200 available numbers.

Premium Numbering? Display numbers not in sequential order?

Can we mark certain numbers as premium? Ideally we would have two tiers for the following scenarios:

Select Numbers ($40)

Premium Number ($200)

  • Especially nice numbers (5+ repeating digits like this)
  • 212 area numbers with 3+ repeating digits

It would also be nice to display premium numbers and the easiest numbers for us to provision first (BulkVS, Teli & Endstream), while providing numbers across multiple NPANXXes, with a toggle back to sequential list mode. That way our users see the variety in numbering resources that we offer.

Make Ingest cycle times configurable

At the moment the cycle times that define how often a specific provider will be ingested from are hard coded in the application. This means that modifying this requires a commit to be made, the CD/CI pipeline to be run, and a release to be executed before they can be changed on the production server.

This is not ideal. Instead these values should be configurable through a section in the appsettings.json file of the NumberSearch.Ingest project so that they can be changed without requiring the application to be redeployed.

Save a copy of the emails sent by the Ordering process

Right now no record is made when the emails are sent out to the customer and to the orders inbox. We should save a copy of these emails and associate them with the order so that we can review them later if something goes wrong or see previous automated emails that went out to the customer. If the emails fail to send we should place a button in the Ops app to attempt to resend them and make a note in the Mvc app's log file. Failure to send the confirmation emails should not break the ordering process or send users to the error page. We want to handle email sending failures gracefully and not scare our customers.

Fix next button on Ops application

This seems to be the same bug as issue #38 where the next button is disabled on the 2nd to last page of results, though it is affecting the ops application and preventing users from going to the last page of available numbers after logging in and navigating to Numbers => Numbers and searching for available numbers.

Screenshot from 2020-07-19 16-36-36

Create an Onboarding page

Create a page so that new customers can be on-boarded to Accelerate Networks by sales and support reps.

Erxes Integration

We use Erxes to handle our clients and leads. Perhaps an integration would be useful, prepopulating a company and customer when an order is submitted. API Docs & Erxes API are here.

Show purchased numbers on completed orders after the number is removed from database

Currently when a number is ordered, we buy it with the upstream vendor. When the next ingest occurs, the number is removed from the database and zeros are shown in the order reference link that is emailed to the client and our orders team.

Can we show the ordered numbers persistently? Since we bought the number, the number not being available for purchase is expected behavior.

Split ingest process

Based on the ingest reporting, splitting the ingest process for each vendor could help our database contain fewer stale numbers.

As part of this, could we import new numbers from BulkVS hourly and expire numbers retrieved from BulkVS that are 1 hour old or older? FirstCom has very little churn, and Teli takes quite a long time to scrape (perhaps scrape Teli & FirstCom twice daily?)

Invalidate Ingested Phone Numbers that are not re-Ingested

We don't want customers to see stale data that can't actually be purchased. Every time we run the ingest process we need to remove the numbers that were not found again.

I see a few ways to do this:

  • TRUNCATE the existing PhoneNumbers table before ingesting the new numbers.
  • Keep track of the ingest date of each number and remove them from the table after a period of time.
  • Compare the existing table to the list of newly ingest numbers and only keep the numbers that are new or match.

Trouble running ops app on Debian 10

When manually invoking the Ops app I get the following error:

root@numberSearch:/var/www/NumberSearch.Ops# dotnet NumberSearch.Ops.dll
System.IO.FileNotFoundException: Unable to find the specified file.
   at Interop.Sys.GetCwdHelper(Byte* ptr, Int32 bufferSize)
   at Interop.Sys.GetCwd()
   at System.Environment.get_CurrentDirectory()
   at System.IO.Directory.GetCurrentDirectory()
   at Microsoft.DotNet.CommandFactory.CommandResolver.TryResolveCommandSpec(ICommandResolverPolicy commandResolverPolicy, String commandName, IEnumerable`1 args, NuGetFramework framework, String configuration, String outputPath, String applicationName)
   at Microsoft.DotNet.CommandFactory.CommandFactoryUsingResolver.Create(ICommandResolverPolicy commandResolverPolicy, String commandName, IEnumerable`1 args, NuGetFramework framework, String configuration, String outputPath, String applicationName)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)

Cart system

Implement a cart system so users can select multiple numbers. Perhaps allow the user to write a note about what each number is for (and capture the search query they used to find the number?).

Add a robots.txt file

The telemetry shows consistent requests failing to find a robots.txt file. We should add one to appease these bots.

Collect information required to process a port request

In addition to the information we collect on #28, we also need to gather the following information to port a phone number. Ideally, we would have a review queue where an employee would check a port request before it is submitted to this API.

Often, clients do not know all of this information or provide us the billing address or an incorrect contact that is not listed as an authorized person on the account. We can usually clean this up with a quick review of the client's bill.

Billing Phone - Also known as the BTN. This is the number that is normally provided on a copy of your bill or statement in the upper right corner or is the first number listed on the bill.
Location Type - Designates if this is a business address or a residential address.
Business Contact - This is the name of the owner or contact who will be submitting the port order.
Business Name - Name of the business associated with the numbers being ported.
Account Number - The account number is usually found on the invoice or a copy of a bill from your current provider.
Service Address - The physical address of where these phone numbers are being used. This information is also on file with your current provider.
Service City - The city of the service address listed above.
Service State - The state of the service address listed above.
Service ZIP - The five digit ZIP code of the service address listed above.
Partial Port - Designates whether or not this will be cancelling all services on the account or leave remaining services and port only the specified numbers in the port order. Some carriers do not respect this request, please check with your old carrier!
Partial Port Description - Describe what services the old carrier should leave alone. Contact the old carrier to confirm they will leave these services intact.
Wireless Number - Set to "Yes" if this is a wireless or cellphone number being ported.
Signature - The signature is needed in order to submit a port order. It is perfectly fine to use the mouse to the best of your ability to sign for this port request. Teli uses Signature Pad v1.5.3 with a size of 200px height and 400px width.
Caller ID - Sets Caller ID (aka CNAM) for all numbers in this port order, 15 character limit.
Numbers - The numbers that will be ported to Accelerate Networks on this port order.
Bill (file upload)

Add a Cart System

In order to enable the purchase of multiple phone numbers and associate the purchase of phone numbers with on-boarding orders we need a cart system to track what items the user is selecting.

Improve String Highlighting

Ideally we would handle searches like to**1 where a result for (309) 886-0012 would have a subtext of (309) 8to-0012 below the number result.

Enable the submission of Phone Numbers to be Ported in

Right now there's no way for some one to submit a phone number that they would like to Port into their cart. This would be a good piece of functionality to add as Phone Numbers are commonly ported in when customer's are onboarded.

Pass the unmodified search query through to the results page

Searching for a word returns that word translated into digits prefilled in the search field, rather than the original query. To ensure users are not disoriented by our number search we should return the original search query prefilled in the search field.

Paginate search results

Right now if you use a blank query or a single * it will return all of the numbers available in the database. This is not ideal because it will crash most browsers.

Update home page with an active background

We created some marketing videos in early 2020 that are in Nextcloud (shared with @uncheckederror), perhaps we could make the homepage default to rolling through those and push the current carousel of phones further down the page?

Likely need to convert the videos to webm, gifv or some other web friendly format...

Potential issue with OAuth in the Ops application?

It looks like the OAuth portion of the Ops application is causing crashes?

Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Jul 19 18:41:36 numberSearch dotnet[20854]: fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3]
Jul 19 18:41:36 numberSearch dotnet[20854]:       An exception was thrown attempting to execute the error handler.
Jul 19 18:41:36 numberSearch dotnet[20854]: System.ArgumentException: The 'ClientId' option must be provided. (Parameter 'ClientId')
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions.Validate()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions.Validate(String scheme)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationBuilder.<>c__DisplayClass4_0`2.<AddSchemeHelper>b__1(TOptions o)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.ValidateOptions`1.Validate(String name, TOptions options)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
Jul 19 18:41:36 numberSearch dotnet[20854]: --- End of stack trace from previous location where exception was thrown ---
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.CreateValue()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.get_Value()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
Jul 19 18:41:36 numberSearch dotnet[20854]: fail: Microsoft.AspNetCore.Server.Kestrel[13]
Jul 19 18:41:36 numberSearch dotnet[20854]:       Connection id "0HM1C9O4VSULS", Request id "0HM1C9O4VSULS:00000001": An unhandled exception was thrown by the application.
Jul 19 18:41:36 numberSearch dotnet[20854]: System.ArgumentException: The 'ClientId' option must be provided. (Parameter 'ClientId')
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions.Validate()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions.Validate(String scheme)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationBuilder.<>c__DisplayClass4_0`2.<AddSchemeHelper>b__1(TOptions o)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.ValidateOptions`1.Validate(String name, TOptions options)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
Jul 19 18:41:36 numberSearch dotnet[20854]: --- End of stack trace from previous location where exception was thrown ---
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.CreateValue()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at System.Lazy`1.get_Value()
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Jul 19 18:41:36 numberSearch dotnet[20854]:    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.