* Define project as a Go module and update dependency versions
Signed-off-by: Nikos Filippakis <me@nfil.dev>
* Update docs, configs and dockerfile to use latest Go version
Signed-off-by: Nikos Filippakis <me@nfil.dev>
* Add postgres database driver
Signed-off-by: Nikos Filippakis <me@nfil.dev>
We exclusively view logs using `less` and `tail`. These do not read JSON well.
Logging as JSON makes it a PITA to read logs and debug problems. We do not
appear to make use of JSON logging, and have no good terminal-based
structured log viewer either.
As a result, I've now removed JSON logging from this project and replaced it
with the standard `TextFormatter` (colors off). This still logs in a structured
way:
```
time="2016-11-18 16:25:46.787373" level=info msg="Got filter ID" filter=717 syncing=1 user_id="@goneb:localhost"
time="2016-11-18 16:25:46.787525" level=info msg="Starting sync" next_batch="s26928_287972_2_1029_26_1_2" syncing=1 user_id="@goneb:localhost"
```
So we can still analyse logs sanely at a later date should we need to. This
feels like the best compromise here between pragmatism and ideals.
- Pass in an `envVars` struct rather than grabbing directly from `os`.
- Accept a `ServeMux` rather than always using the default mux.
- Add a `_test.go` file to instrument Go-NEB using `TestMain` to call `setup()`
Because apparently "Feed Reader" is the name of a thing popular enough that we
don't want to step on toes, so let's call it the name of a less popular thing.
Just need to send messages into rooms now for a first cut to be done. Notable
improvements to make:
- We currently do 1 goroutine per service. This could be bad if we have lots of these things running around.
- We do not cache the response to RSS feeds. If we have 10 independent services on the same feed URL, we will
hit the URL 10 times. This is similar to how we currently do 1 webhook/service, so it's plausible that in
the future we will want to have some kind of generic caching layer.
- We don't send messages to Matrix yet. We need a `Clients` instance but can't get at one. There's only ever
one, so I wonder if we should global it like we do with `GetServiceDB()` for ease of use?
- The polling interval is divorced from the actual feed repoll time. Ideally we would schedule the goroutine
only when we need it, rather than checking frequently, determining we have nothing to do, and going back
to sleep.
* WIP: Initial Guggy
* Finish Guggy integration
* typo & send No GIF Found when GIF string empty
* unused function
* Unused import, HTTPS API and GIFs
* APIKey -> api_key
* Use api_key on the wire, APIKey in structs
Allows users to nuke their OAuth credentials. Currently this just does a database
`DELETE` as neither Github nor JIRA need you to hit any special `/logout` API.
Previously, we would notify `Services` based on matching the `room_id` of the
event with a list of `RoomIDs()` which the service returned.
Now we notify `Services` based on matching the `user_id` of the client listening
for events. This means that the service will receive more events because there
isn't a filter on a set of room IDs.
This is required in order to implement "auto-join on invite" semantics for
Services, as the room ID is not known at that point in time.
Add a new `AuthSession` function `Authenticated()` which returns `true` if the
user has completed the auth process. This allows the caller to distinguish
between:
- Never done any auth (404s)
- In the process of doing auth (`Authenticated == false`)
- Finished doing auth (`Authenticated == true`)
- Rename the path from /configureAuthSession to /requestAuthSession
- Add a global getter/setter for the `ServiceDB` : this avoids cyclical deps
because now the Realm wants access to the database, and due to the factory
pattern it would mean `types.go` would need to import `database`, but
`database` is already doing so to invoke the factory function in `schema.go`.
- Modify how `AuthSession` is loaded/stored in the database. Now it is just
a blunt JSON store for Public fields. It is initialised via a new Realm
interface function `AuthSession(userID, realmID)` which is there to return
the right `struct` so stuff can be unmarshalled into it.
- Add a new Realm interface function `RequestAuthSession` which is invoked
when `/requestAuthSession` is hit. It is a direct request/response mapping,
a JSON blob goes in as a param, and a JSON blob comes out as the return.
The Realm is free to create/load/update/delete `AuthSessions` inside the
function. This allows better control over when new sessions are made (or
whether to return an existing session).
Auth sessions are a single auth process between a user and an auth realm. As
such, they are keyed off the tuple of `(user_id, realm_id)`.
Only the realm which they belong to knows how to construct them, hence all
"load" sections require an `AuthRealm` to be extracted first.
Currently I pass in a `json.RawMessage` rather than factory initialise and
clobber public fields based on the JSON, we can always change that if need be
later down the line.
Overall, this feels really nice (when starting to add in GH auth, everything I
wanted was already there in the right place waiting for me).