[HN Gopher] Show HN: Caffeine - Minimum viable back end for prot...
       ___________________________________________________________________
        
       Show HN: Caffeine - Minimum viable back end for prototyping
        
       Author : aw4y
       Score  : 196 points
       Date   : 2021-11-16 09:25 UTC (13 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | gwbas1c wrote:
       | At a minimum, this should be password protected _by default._
       | 
       | One of the security lessons from the late 1990s and early 2000s
       | is that things like this quickly get hacked. Many developers
       | forget that a service where all security is handled client-side
       | are easy targets for hacking.
       | 
       | Furthermore: In a lot of cases, people will ship prototypes and
       | run their stuff on top of them long after they have outgrown a
       | critical component.
       | 
       | I have tried to write a universal backend... It's possible, but
       | you really have to work in a permissions model from the
       | beginning. What you'll find is that basic read/write/own enables
       | very basic functionality. Unfortunately, to do anything
       | complicated, you will need to write server-side queries that
       | verify that the user is allowed to do what they are trying to do.
        
         | btbuildem wrote:
         | Pretty sure this is meant for prototyping and maybe demoing in
         | controlled environments.
         | 
         | As soon as you involve auth, things get boring and annoying.
        
           | throw_m239339 wrote:
           | > As soon as you involve auth, things get boring and
           | annoying.
           | 
           | No, JWT is easy enough to implement.
        
             | Spivak wrote:
             | JWT is crazy annoying compared to "pass an API key" in the
             | header.
        
               | throw_m239339 wrote:
               | > JWT is crazy annoying compared to "pass an API key" in
               | the header.
               | 
               | An API key and a JSON WEB TOKEN have a completely
               | different purpose. API keys don't solve authorization.
               | 
               | A single JWT provider can authorize many different
               | servers.
               | 
               | Furthermore Go already have several good JWT libraries.
        
               | Spivak wrote:
               | And JWT's don't solve authentication which was the actual
               | problem people were looking to solve. For a prototyping
               | server authn==authz is more than fine.
        
               | throw_m239339 wrote:
               | > And JWT's don't solve authentication which was the
               | actual problem people were looking to solve. For a
               | prototyping server authn==authz is more than fine.
               | 
               | Re-read the OP
               | 
               | > Unfortunately, to do anything complicated, you will
               | need to write server-side queries that verify that the
               | user is allowed to do what they are trying to do.
               | 
               | this is authorization, not authentication. Your assertion
               | is false at first place.
               | 
               | Your comment makes no sense by the way. You'd have the
               | exact same issue with another authorization scheme, the
               | credentials need to come from somewhere.
               | 
               | There no such thing as "prototyping servers" in the wild.
               | Only blatantly unsecure open source servers.
        
               | notsureaboutpg wrote:
               | It really isn't. There are off the shelf libraries and
               | you can keep JWTs alive forever. You don't have to do
               | refresh tokens, etc.
               | 
               | Bare minimum JWT implementation is easy.
        
           | gwbas1c wrote:
           | Honestly, anything simple. It could be as brain-dead simple
           | as passing a password on the command-line, and then requiring
           | the password as a header.
        
             | brazzledazzle wrote:
             | As much as I hate saying it even a simple token in a url
             | parameter might be ok for a prototype.
        
       | l30n4da5 wrote:
       | `"CREATE TABLE IF NOT EXISTS %v ( id text PRIMARY KEY, data json
       | NOT NULL)"`
       | 
       | Correct me if I'm wrong, as I havent used Postgres in a few
       | years, but doesn't the `json` column in Postgres just store the
       | data as text?
       | 
       | Last I knew, jsonb was much more efficient/performant for queries
       | and storage, while having a very robust api for querying specific
       | properties.
       | 
       | Curious what the reasoning was for using json rather than jsonb.
        
         | mccolin wrote:
         | Correct. The json data type is less performant and stores the
         | data more or less as lightly indexed text. jsonb optimizes the
         | storage format and allows for more JSON operations, such as
         | extracting individual keys.
         | 
         | For this product, if the super-generic API doesn't
         | offer/require a need to do complex operations, though, json may
         | be adequate to lookup items by id and present them.
        
       | aw4y wrote:
       | A very basic REST service for JSON data - enough for prototyping
       | and MVPs!
       | 
       | Features:                   no need to set up a database, all
       | data is managed automagically*         REST paradigm CRUD for
       | multiple entities/namespaces         schema validation
       | search using jq like syntax          CORS enabled         easy to
       | deploy as container
        
         | torgard wrote:
         | Just a heads-up, you might want to take down the example
         | website. Now that it's been posted to HN you might see
         | malicious actors.
         | 
         | I also think it's prone to SQL injection at the moment? At
         | least, it's raising a syntax error when inputting an
         | apostrophe.
        
           | grey-area wrote:
           | Yes, don't do this:
           | 
           | https://github.com/rehacktive/caffeine/blob/master/database/.
           | ..
           | 
           | "INSERT INTO %v (id, data) VALUES('%v','%v') ON CONFLICT (id)
           | DO UPDATE SET data = '%v'"
           | 
           | Use prepared statements and parameters passed to the db
           | driver, not building strings with strings or you are
           | vulnerable to sqli.
           | 
           | I'd also avoid using %v anyway when building strings - safer
           | to use a specific type like %d for int.
        
             | johnday wrote:
             | You're right of course, but I think the idea of this
             | software is that the user (and, by extension, their input)
             | are trusted.
        
               | grey-area wrote:
               | Good to start with the right habits. People will put this
               | on the internet, the author did for example.
        
               | throw_m239339 wrote:
               | > You're right of course, but I think the idea of this
               | software is that the user (and, by extension, their
               | input) are trusted.
               | 
               | No, you should enforce the most basic security practices
               | even if the users are "trusted". Somebody might put that
               | on the internet for a demo for client and get hacked in
               | no time, because the code is opened to SQL injection.
               | This isn't acceptable. There are minimum security
               | standards every project should follow.
               | 
               | And since none of the minimum security standards are
               | implemented in that project, I would not recommend using
               | it until they are.
        
               | johnday wrote:
               | I'm not sure what you are "no"-ing. I agreed with the
               | parent comment.
        
             | aw4y wrote:
             | the reason I went "quick'n dirty" is for the prototyping
             | nature of the project. But I'll fix this anyway, thanks!
        
               | Cthulhu_ wrote:
               | There's nothing as permanent as a temporary solution.
               | There's been countless SQL injection vulnerabilities
               | exploited over the past decades with the "I'll fix it
               | later" mindset.
               | 
               | Start with prepared statements by default, they are not
               | more work than formatting strings.
        
               | robmccoll wrote:
               | Using the db Exec / Query / Query row is the same amount
               | of code and effort the fmt.Sprintf statements. Even in
               | quick-and-dirty mock-ups, it's a good idea to not cut
               | corners there.
        
             | mahogany wrote:
             | Are you saying that %v should be avoided in general, or
             | just in the context of queries? (Go noob who doesn't
             | understand %v)
        
               | robmccoll wrote:
               | In queries, you should use the database/sql.DB interface
               | if possible with your database
               | https://pkg.go.dev/database/sql#DB.Exec
               | 
               | It should sanitize / quote arguments for you and protect
               | against SQL injection. Note that this doesn't mean all
               | data sanitization is performed, just the basic '; do my
               | stuff here; -- type of things.
        
               | grey-area wrote:
               | First, don't build strings like this for sql.
               | 
               | But for other strings built with sprintf, yes I am saying
               | don't use %v unless for debugging, it's just one more
               | avenue where you might be surprised by input, even if
               | you're not building strings for sql. For example, someone
               | might do this with user supplied data:
               | 
               | myoutput := fmt.Sprintf("user:%v",userID)
               | 
               | and if userID is a string like "foo" it'll end up in
               | their string and they won't get what they expect. So
               | better to just put another guardrail on there and insist
               | that the param is an integer or whatever you expect by
               | using %d which will only accept an int - this means you
               | have to convert it to an integer first.
               | 
               | Many vulnerabilities are caused by data not being in the
               | format people expect (not just sqli).
        
           | samstave wrote:
           | >> _Now that it 's been posted to HN you might see malicious
           | actors._
           | 
           | This needs to be an HN fN Masterclass by @Dang....
           | 
           | We should have regular visibility into /how/ HN is used by
           | malicious actors.... HN has enough pedigree to get some
           | insight from some of the top security folks... and it would
           | be REALLY good to know how HN is being harvested in this
           | space.
        
           | lupire wrote:
           | Why? That shows important information about the quality of
           | the product.
        
       | hashimotonomora wrote:
       | Why do people overload common nouns so much when naming a
       | project? A name should confer its essence.
        
         | ABraidotti wrote:
         | Caffeine suggests a jump start, which is what this tool
         | purports to do.
        
         | lmilcin wrote:
         | You know, naming is one of the two really hard problems in CS.
         | But there is apparently a hack which is to open dictionary on
         | random page and point your finger on random word.
         | 
         | My next application is going to be called Toreutics which is
         | going to break this word for every person that actually uses
         | it.
         | 
         | Kinda like breaking the word Meta. Which I suppose is actually
         | aimed at making things difficult to search for.
        
       | kjgkjhfkjf wrote:
       | Very cool. You could simplify the tests by using testify [0]
       | assertions and possibly a test suite. Then it'd be easier to add
       | additional test cases.
       | 
       | [0] https://github.com/stretchr/testify
        
       | shireboy wrote:
       | I could have used something similar recently, but that persisted
       | to disk as json. I ended up just storing a wad of JSON on disk
       | and memory, loading and saving as needed. Will only ever be 1M or
       | so and only 2 users.
        
       | cpursley wrote:
       | This is useful. But you can achieve the same results in just a
       | few more steps with Hasura or Supabase and end up with something
       | that is close to production ready.
        
         | kall wrote:
         | Yeah, I would probably go hasura if I needed this, but I can
         | see the appeal of something that is a single component you can
         | self host and self understand. Hasura is rock solid, but I will
         | never read through it's haskell source or understand how it
         | constructs those extra-clever postgres queries.
         | 
         | If I read it right, you don't need to configure any schema to
         | use this? You can just POST a user and it will create that
         | type? If it's true, that's a real step above hasura/supabase
         | for rapid prototyping.
        
           | aw4y wrote:
           | yes, no schema required (but you can add it if you want
           | validation)
        
         | [deleted]
        
       | nkozyra wrote:
       | I realize this is just for prototyping but it looks like it just
       | spits sprintf SQL strings into the database.
       | 
       | While not a security risk if done locally, why not just use a
       | where string builder to generate the $ values and a variadic as
       | the input? It's about the same amount of work.
        
       | quickthrower2 wrote:
       | Like the idea. Any user auth?
       | 
       | I wonder if parse is still around and supported? I thought that
       | was pretty good for this kinda thing.
        
         | enstyled wrote:
         | Parse is still around and supported: https://github.com/parse-
         | community/parse-server
        
           | IggleSniggle wrote:
           | This is bizarre. I spent a good 5+ min looking over the
           | README and documentation site, and couldn't find out what
           | that project is other than "a backend that runs on Nodejs."
           | Yeah ok but what is it? Why am I interested? I'm not looking
           | to be sold, just for it to tell me what it's for. I have some
           | assumptions based on how I got linked there, but this is
           | surprising to me.
        
             | quickthrower2 wrote:
             | In a nutshell a place for your web page or mobile app to
             | store and retrieve data. There is some auth, business logic
             | / security stuff but not as much as you get in an MVC web
             | app. Let's you build apps where a lot of the work happens
             | on the front end and the back end is basically a place to
             | save to disk.
             | 
             | Parse was a startup but they shut down and open sourced
             | their code.
        
             | [deleted]
        
         | berkes wrote:
         | If you mean https://parseplatform.org/ then it looks to be
         | still around.
        
         | WolfOliver wrote:
         | I think auth is the trickiest thing to solve in a BaaS
         | solution. Could not find anything in the readme about it.
        
       | josh_carterPDX wrote:
       | We tried to do this back in 2016 with BrightWork. We got a lot of
       | traction, but it came on the heels of Parse being shutdown by
       | Facebook after acquiring them for a ton of money.
       | 
       | The lesson I learned from that experience is that there is still
       | a tremendous amount of distrust in platforms that make it easy to
       | stand up something quickly. Even prototyping.
       | 
       | Even if you make it easy for users to export their code from your
       | platform you will still run into scalability questions (i.e. what
       | happens if someone builds the next Flappy Bird on your
       | platform?).
       | 
       | All that aside, this is great! Congrats on launching Caffeine. :)
        
       | jpdelatorre wrote:
       | Another similar project that I use for mocking API server
       | https://github.com/typicode/json-server
        
       | miki_tyler wrote:
       | This awesome! Our product supports json as a backend in a very
       | simple way in order to feed data to HTML templates
       | (https://www.stack55.com) and I was thinking of doing something
       | very similar to what you have done.
        
         | aw4y wrote:
         | very cool :)
        
       | manx wrote:
       | Very nice idea! I haven't seen anything like it.
        
         | mikkelenzo wrote:
         | Looks great indeed
        
       | hardwaresofton wrote:
       | Nice to see that the interface for the DB was separated out:
       | 
       | https://github.com/rehacktive/caffeine/blob/master/service/s...
       | 
       | It's not "MVP" fashion but even for only one implementation
       | making these interfaces is critical IMO.
       | 
       | That said, if it's not too much maybe consider adding a SQLite
       | backend! :)
        
         | aw4y wrote:
         | the SQLite implementation is in TODO :)
        
       | sgt wrote:
       | This may become very useful! I will definitely check it out.
        
       | rightly wrote:
       | Similar project -> https://sheet2api.com/
        
         | Wronnay wrote:
         | Only 25 rows are supported in the free plan and the other plans
         | are more expensive.
         | 
         | I don't think this has a good price-performance ratio - all
         | other solutions I know are cheaper...
        
       | thih9 wrote:
       | FYI, there is a name clash with Caffeine, a Mac OS menu bar app
       | that keeps the screen awake:
       | https://intelliscapesolutions.com/apps/caffeine . But I guess
       | this is expected with a name like this, and the scopes of the
       | projects are clearly different, so this should be relatively
       | harmless.
        
         | lekevicius wrote:
         | You don't need an app. `caffeinate` is a command line utility
         | built into macOS.
        
         | Danidada wrote:
         | And also a (very efficient) Java cache library
         | https://github.com/ben-manes/caffeine
        
         | jamesmishra wrote:
         | Caffeine is also a central nervous system stimulant of the
         | methylxanthine class.
        
         | das_keyboard wrote:
         | Since we are collecting :) there is also a streaming service
         | https://www.caffeine.tv/
        
         | cozzyd wrote:
         | And a gnome shell extension that does the same thing.
        
       | theK wrote:
       | Cool project! Personally I've been using apiary or Snowboard for
       | Backend prototyping since they allow for a design first approach
       | and typically end up with quite good Dokumentation and Testing
       | infrastructure. But having a real interactive back end like
       | caffeine provides is also very intriguing!
        
       | blintz wrote:
       | Cool! I like that it's zero config to start with, and that adding
       | schemas can itself just be done with a request.
        
       | brainzap wrote:
       | A few requests should randomly fail to force the developer to
       | think about handling errors. :)
        
         | codefined wrote:
         | Hah! I'm not sure my MVP has ever had error handling beyond
         | "Something went wrong.". That's something for a real production
         | app, not the minimum possible product.
        
           | [deleted]
        
         | Method5440 wrote:
         | You guys have errors in your programs? :)
         | 
         | Jokes aside... chaos engineering is a big deal right now - this
         | isn't a terrible idea and might be worthy of a fork.
        
       | lhorie wrote:
       | Shameless plug: along the same lines, but for rapid web UI
       | prototyping cases where you don't want to waste time with setting
       | up a server, I built a tiny tool called REM[0] a few years ago.
       | 
       | It never actually stores data on the server (it echos it into a
       | cookie instead), so the dataset is only ever visible to you, no
       | auth or service keys required.
       | 
       | [0] http://rem-rest-api.herokuapp.com/
        
       | sgt wrote:
       | Feature request: supply .json file via command line to pre-load
       | data into the in-memory database.
       | 
       | Taking it even further; how about persisting the data in the
       | file?
       | 
       | Sometimes your prototype will need some pre-added data so I think
       | this might be useful.
        
         | lofties wrote:
         | Can probably do that with some `jq` and CURL magic already!
        
         | aw4y wrote:
         | currently there are two implementation for the database
         | "behind": in memory or with postgres, both with zero config
         | (except for starting an instance of postgres, in the second
         | case!). it can be easily extended to use files as persistence,
         | good idea :)
         | 
         | regarding the pre-population, you can just make a quick script
         | with curl that will add some data after you run the service.
         | any thought?
        
           | nicoburns wrote:
           | SQLite could also be a good option
        
           | tbrock wrote:
           | Thats code folks would have to write instead of focusing on
           | the MVP, it would be better if this loaded it by convention.
        
         | qw wrote:
         | I have used WireMock in the past that supports pre-defined
         | mocks. It can be run both locally and as a service (I only ran
         | it locally)
         | 
         | http://wiremock.org/
         | 
         | It's more complex than Caffeine, but it has a lot of options.
         | 
         | It can also run as a proxy and generate the mocks from actual
         | http requests passing through the proxy
        
         | skhm wrote:
         | My first thought too, but I guess it's also very easy to hand-
         | roll an init_data.sh script with a bunch of POST curls to
         | populate the DB.
        
           | aw4y wrote:
           | exactly!
        
       | kypro wrote:
       | Sorry if this is a little off topic, but what is it with devs and
       | naming projects Caffeine?
       | 
       | Am I the only person who rolls their eyes when I see another
       | Caffeine / Coffee named project?
        
         | anon_cow1111 wrote:
         | I wish devs would stop naming _EVERYTHING_ after common english
         | words; it makes stuff 10 times harder to troubleshoot unless
         | you already rank high on the search results.
         | 
         | I guess HN would be the best place to bring this up in a psa
         | topic but I doubt it'll have any long-term influence...
        
         | samatman wrote:
         | Imagine if Gosling had gone with Oak, there are so many more
         | trees to work with.
         | 
         | Of course Indonesian islands were the other possibility...
        
       ___________________________________________________________________
       (page generated 2021-11-16 23:01 UTC)