Spamhouse is a graphql server that adds ips to a local storage and detemines whether the IPs are in spamhous block list.
make dev
Access the GraphQL browser UI at http://localhost:8080. The UI uses basic authentication, and as such the credentials are bootstrapped at application startup. The default credentials are: secureworks/supersecret. To modify default credentials, specify them as environment variables: DEFAULT_USER
and DEFAULT_USER_PASSWORD
in docker-compose.yml
The application port default is 8080, to modify the port the application is running on, modify the PORT
number in the Makefile
To create a new entry, used the mutation below in the GraphQL UI.
mutation{
enqueue(input: ["1.2.3.4"]){
status
errors
}
}
To retrieve an existing entry, specify the query as follows:
query{
getIPDetails(input: "1.2.3.4"){
node{
ip_address
response_code
uuid
created_at
updated_at
}
}
}
make run
stops/starts the server without building the appplication
make stop
make db-shell
Creates a shell into sqlite3. See instructions for sqlite3 here
make test
Runs go tests locally. Makes uses of golang build tags to only trigger local tests with !integration
make test-integration
Runs integration tests. Makes uses of build tags to only trigger integration tests.
- To extend database access, modify repo.go
- To modify the graphql resolvers, modify gqlgen.yml, after the changes are saved, run
make regenerate
- To update auth (e.g. add database user validation) update auth.go
-
Your API must be protected with basic authentication
- Username: secureworks
- Password: supersecret
-
You should have a GraphQL API that is available via a /graphql endpoint
- We suggest using https://gqlgen.com/
- Mutations
-
enqueue(ip: [“ip1”, “ip2”])
- This should kick off a background job to do the DNS lookup and store it in the database for each IP passed in for future lookups
- If the lookup has already happened, this should queue it up again and update the response and updated_at fields
-
Queries
- getIPDetails(ip: “ip address here”)
-
It should look up the IP in the database
-
If it’s not there, it should respond with the appropriate response code
-
This should have:
- uuid ID
- created_at time
- updated_at time
- response_code string
- ip_address string
-
- getIPDetails(ip: “ip address here”)
-
- Mutations
- We suggest using https://gqlgen.com/
-
You should use SQLite as your database to make this portable
-
Dependencies should be handled using go mod
-
Tests should be written for the key components of the system
-
A README is required and should explain how to develop and run the project as if it were a new team member working on it
-
The application should be packaged as a Dockerfile, and should accept a PORT environment variable to know which port to run on
-
You can use any external libraries you want, but you must document and explain why you’re using them
- gorm - golang orm, used it for migration simplicity mainly.
- logrus - structured logger utility, better than printf :)
- testify - testify, utility for test assertion
- backoff - backoff utility, used for ensuring db is up before staring up the application
- envconfig - utility library for environment variable configuration
- chi - Added chi for injecting auth middleware
- gqlgen - graphql, per the requirements suggestion
- uuid - generate UUID, used for generating uuid before inserting ip entry into database. See BeforeCreate hook in model
- Initially I had implemented the queuing process to return the ips added upon enqueueing. See commit, however, I recognized that ultimately this was not the best approach since it would dpeend on each ip returning after it had been refreshed.