about summary refs log tree commit diff
path: root/monzo_ynab
AgeCommit message (Collapse)AuthorFilesLines
2020-02-10 Begin work on YNAB clientWilliam Carroll4-1/+70
After reading these docs https://api.youneedabudget.com/v1#/Transactions/createTransaction I successfully made a request to post a transaction to my YNAB account. Hastily created a client.go that doesn't contain much at the moment.
2020-02-10 Refactor token server initializationWilliam Carroll1-30/+42
- Move state "gen server" to the top of main/0 - Initialize it as empty - Ensure that persistTokens/2 is called whenever the state changes - Support setState/2 (similar in spirit to getState/0)
2020-02-10 Debug os.Signal handlingWilliam Carroll1-12/+11
Problem: When SIGINT signals we're sent to the token server, it would shut down without completing the shutdown procedure. The shutdown procedure would persist the application state (i.e. access and refresh tokens). This is problematic for the following sequence of events: t0. Access and refresh tokens retrieved from kv.json and used as app state. t1. Tokens are refreshed but not persisted. (I'm still unsure how this happens). Remember that this means the previous access and refresh tokens from t0 are now invalid. t2. User sends a SIGINT. t3. Token server shuts down. t4. Token server is restarted, kv.json is used as the app state even though its tokens are now invalid. t5. Tokens are attempted to refresh, Monzo API rejects the tokens because they're invalid. Now we need to provide the token server with valid access and refresh tokens otherwise we will repeat the loop described above. This means going through the client authorization flow again or copying and pasting the tokens logged from the token server into kv.json. Either scenario is more manual than I'd prefer. Solution: Use a buffered channel to receive the os.Signal. I got this idea after reading these docs: https://golang.org/pkg/os/signal/#Notify and I debugged this issue shortly thereafter. I also rearranged the order of operations in main/0 to ensure that handleInterrupts/0, which registers the event listeners, occurs before scheduleTokenRefresh/2 is called. This allows the token server to gracefully shutdown even if it's in the middle of the scheduleTokenRefresh/2 call.
2020-02-10 Sketch Monzo clientWilliam Carroll1-0/+52
None of this code is functional at the moment. I'm just writing some ideas of how I'd like to work.
2020-02-10 Consume auth libraryWilliam Carroll1-58/+102
Consume the newly relocated auth package. Additionally: - Debugged error where JSON was properly decoding but not populating the refreshTokenResponse struct, so my application was signaling false positive messages about token refresh events. - Logging more often and more data to help my troubleshooting - Refreshing tokens as soon as the app starts just to be safe - Clean up the code in general
2020-02-10 Move authorization logic into separate packageWilliam Carroll3-146/+115
Relocated the logic for authorizing clients into a separate package that the tokens server now depends on. Moving this helped me separate concerns. I removed a few top-level variables and tried to write more pure versions of the authorization functions to avoid leaking Monzo-specific details.
2020-02-10 Gracefully shutdown serverWilliam Carroll1-0/+33
Listen for SIGINT and SIGTERM signals and write the current state to the key-value store before shutting down.
2020-02-10 Read tokens from store when server startsWilliam Carroll1-3/+14
Attempting to read the persisted tokens from the key-value store when the server begins. The server currently fails when those values are empty. TODO - Consider adding logic for knowing if the cached tokens are expired and prompt the user to reauthorize the client using a web browser.
2020-02-10 Nixify tokens.goWilliam Carroll2-1/+22
- Package tokens.go with Nix - Add monzo_ynab.{job,tokens} to shell.nix
2020-02-10 Remove dead codeWilliam Carroll1-18/+0
Removing a half-baked Monzo HTTP client. A more fully supported and differently designed one is forthcoming.
2020-02-10 Create gopkgs directory for golang libsWilliam Carroll4-66/+19
- Created a gopkgs directory and registered it with default.nix's readTree - Moved monzo_ynab/utils -> gopkgs - Consumed utils.go in main.go - Renamed monzo_ynab -> job
2020-02-10 Create server for managing Monzo credentialsWilliam Carroll4-52/+342
I created a server to manage my access and refresh tokens. This server exposes a larger API than it needs to at the moment, but that should change. The goal is to expose a GET at /token to retrieve a valid access token. The server should take care of refreshing tokens before they expire and getting entirely new tokens, should they become so stale that I need to re-authorize my application. A lot of my development of this project has been clumsy. I'm new to Go; I didn't understand OAuth2.0; I'm learning concurrent programming (outside of the context of comfortable Elixir/Erlang). My habits for writing programs in compiled languages feels amateurish. I find myself dropping log.Println's all over the source code when I should be using proper debugging tools like Delve and properly logging with things like httputil.Dump{Request,Response}. The application right now is in a transitional state. There is still plenty of code in main.go that belongs in tokens.go. For instance, the client authorization code belongs in the tokens server. Another question I haven't answered is where is the monzo client that I can use to make function calls like `monzo.Transactions` or `monzo.Accounts`? The benefit of having a tokens server is that it allows me to maintain state of the tokens while I'm developing. This way, I can stop and start main.go without disturbing the state of the access tokens. Of course this isn't the primary benefit, which is to abstract over the OAuth details and expose an API that gives me an access token whenever I request one. The first benefit that I listed could and perhaps should be solved by introducing some simple persistence. I'd like to write the access tokens to disk when I shutdown the tokens server and read them from disk when I start the tokens server. This will come. I could have done this before introducing the tokens server, and it would have saved me a few hours I think. Where has my time gone? Mostly I've been re-authorizing my client unnecessarily. This process is expensive because it opens a web browser, asks me to enter my email address, sends me an email, I then click the link in that email. Overall this takes maybe 1-3 minutes in total. Before my tokens server existed, however, I was doing this about 10-20 times per hour. It's a little disappointing that I didn't rectify this earlier. I'd like to remain vigilant and avoid making similar workflow mistakes as I move ahead.
2020-02-10 Document more API requestsWilliam Carroll1-6/+32
I'm continuing to use restclient-mode, and I'm enjoying it. Updating the scratch file with more endpoints and credentials.
2020-02-07 Support a restclient.el scratch bufferWilliam Carroll1-0/+10
I've been using restclient.el and `restclient-mode` lately to test API calls, and I'm enjoying. I think it might make sense to track these scratch files in the repo. Who knows? They may serve as a form of documentation.
2020-02-07 Support serde for Monzo and YNAB transaction structsWilliam Carroll2-0/+134
Define transaction structs for both Monzo and YNAB. Each package has a `main` function that runs some shallow but preliminary round-trip tests for the serializers and decoders. The fixtures.json file that each of them is referencing has been ignored in case either contains confidential data of which I'm unaware.
2020-02-07 Support YNAB personal-access-tokenWilliam Carroll2-4/+5
Define my YNAB personal access token as an environment variable. Prefix Monzo environment variables with "monzo_" to more easily differentiate between Monzo credentials and YNAB credentials.
2020-02-07 Support lorriWilliam Carroll2-0/+14
From what I currently understand, lorri is a tool (sponsored by Target) that uses nix and direnv to build and switch between environments quickly and easily. When you run `lorri init` inside of a directory, lorri creates a shell.nix and an .envrc file. The .envrc file calls `eval "$(lorri direnv)"` and the shell.nix calls `<nixpkgs>.mkShell`, which creates a shell environment exposing dependencies on $PATH and environment variables. lorri uses direnv to ensure that $PATH and the environment variables are available depending on your CWD. lorri becomes especially powerful because of Emacs's `direnv-mode`, which ensures that Emacs buffers can access anything exposed by direnv as well. I still need to learn more about how lorri works and how it will affect my workflow, but I'm enjoying what I've seen thus far, and I'm optimistic about the road ahead.
2020-02-05 Support OAuth 2.0 login flow for Monzo APIWilliam Carroll5-0/+203
After some toil and lots of learning, monzo_ynab is receiving access and refresh tokens from Monzo. I can now use these tokens to fetch my transactions from the past 24 hours and then forward them along to YNAB. If YNAB's API requires OAuth 2.0 login flow for authorization, I should be able to set that up in about an hour, which would be much faster than it took me to setup the login flow for Monzo. Learning can be a powerful thing. See the TODOs scattered around for a general idea of some (but not all) of the work that remains. TL;DR - Package monzo_ynab with buildGo - Move some utility functions to sibling packages - Add a README with a project overview, installation instructions, and a brief note about my ideas for deployment Note: I have some outstanding questions about how to manage state in Go. Should I use channels? Should I use a library? Are top-level variables enough? Answers to some or all of these questions and more coming soon...
2020-02-05 Inherit parent's .envrc variablesWilliam Carroll1-0/+5
I discovered direnv's convenient `source_up` function today. I needed it to inherit the values defined in ~/briefcase/.envrc, and it's working exactly as I expected it would. What a fine piece of software direnv is.