DEV Community

DaNeil C
DaNeil C

Posted on • Updated on

p.2 My attempt at building the backend of a password manager

Set up the Ruby on Rails Backend API

This will be part 2 of an unknown number of write ups on my final project at Flatiron, my password manager.
It's taken me forever to write it but here are the steps I took to get the backend up and running. Woot!

  1. Via command line (cause that's the only way I know how to do this) enter the following code where is the name of the folder your project will live. For me I had to first navigate to my developer folder and into my "final project" folder. Once there I ran rails new <my-project> --api -T --database=postgresql The command will set up the rails application as an API and use PostGresSql as the database. (I'm not sure what the "-T" does though...)

  2. I found out that running rails db:create was apparently important before running any migration soooo might as well do this from the beginning.

    • Note: it can be fun after migrations are created but the app will fail if db:create is not run before db:migrate.
  3. Once the app is created be sure to navigate to it and then run rails generate resource <tablename> <columnName>:<columnType> --no-test-framework for each of the tables you want. For my project I have a "user" table, an "account" table, and a "longin" table.

    • By using the "resources" generator we are able to set up all associated controllers, models, views, migrations, and none of the test-frameworks.
    • Note: If the column name is a string there does not need to be a "type" listed with it. Only run 1 resource generator for each table. Don't try doubling up on tables. It's not designed like that.
  4. Now we want to run rails db:migrate. This will run all the migrations that I set up for each table. For my set up I have 4 tables to start.

  5. Go in and set up the relationships for each table. Mine is pretty straight forward as there shouldn't be any "has_many :through" anything. its all "has_many"/"belongs_to"/"has_one" relationship set up.

  6. Oops, I forgot a column on the Users table. An email could be helpful for recovering a lost master password or two-factor-authentication at a later time. Time to add one an remigrate.

    • To add a column to an existing table we can run rails generate migration add_email_to_users email:string and then run the rails db:migrate again and it will be added to my schema. The need to do it like this is so that if I need to reset my database then the migration is there and will be part of it automatically.
  7. Now we need to set up the seed data. The "seed data" is a simple file for some basic data of one or two users to work with. I did 1 user for now and found out that my tables are all messed up and have to rework this.

    • Note: any "belongs_to" relationship needs to have the thing that belongs to a thing keeping track of who it belongs to. An Account keeps track of its User.
  8. Now I need to fix my database. I had to do lots of renaming of things and reworking on it all.

    • Try and keep any names to 1 word as anything more gets very confusing.... I made this mistake. It sucks to fix.
  9. Scrap it all and start over. I broke it and don't know how to fix it. I figure it's easier to restart than try and fix it because I am not really that far in. damn. I will at least be able to follow most of the same steps but I will be checking my plurality and using single words for tables instead of 2.

  10. But really 9.5... Turns out I think I had everything correct BUT I was calling things incorrectly. Because of the way that my models are the plurality of it all was evading me. BUT now it works and I can see the password associated with a user based on its account group and its login information with a users accounts. ".accounts.first.logins.first.password.password_digest"

  11. At this point I wanted to uncomment all of my CORS actions. For those that don't know, CORS stands for Cross-Origin Resource Sharing, and an origin is made up of: the protocol, host, and the port number. "Cross-origin requests, however, mean that servers must implement ways to handle requests from origins outside of their own. CORS allows servers to specify who (i.e., which origins) can access the assets on the server, among many other things."(2) In context of this project, this means that I need to be able to access specific parts of my application but not all of them to keep things secure. I was able to do this temporarily with uncommenting the CORS.rb file in the configuration folder and making the origins all via '*' instead of "example.com'

    • Note:: After the application is launched this will need to be set to a specific address because my front end is hosted on a different site than my back end. THis will need to be changed to where the front end it hosted so that they can talk to each other.
  12. Time to Front End a bit to make sure things connect....

  13. Now that the front end can see the backend API I wanted to implement JSON Web Tokens for logging in. This involved changing my schema up so that passwords were in a "password_digest" column and that the user has a serializer. I had to create a new migration with rails g migration ChangeColumnName and then in the migration add in a rename_column :table_name, :old_column, :new_column Once this was done I was able to ensure that my User model file has a "has_secure_password" and reset my database successfully. (3)

    • For me I had to uncomment rack-cors and bcrypt from my Gemfile as I had not done this yet. (Don't forget to re-"bundle install" so that your Gemfile is uptodate.)
    • Set up a Serializer for each table via rails g serializer :table_name. You will need these later.
    • Ensure that you top table has "has_secure_password" and any other validations you might need/desire. I chose "uniqueness" and "length" for now.Alt Text
    • And I am realizing as I am writing this that I never authenticated the password on login... I did everything on the client-side and nothing on the server-side to store the password except have a password_digest column for the users password. Oops... This will need to be corrected.
  14. Now I need to create a "create" method within my users_controller so that when an account is created it automatically has its password put into a digest there it is hashed with Bcrypt. Alt Text

    • Note: this method of allowing the client-site to validate the user input for creating an account and logging in is unsafe. The user could attempt to put anything into or bypass the forms controls easily (I'll go over testing my application at a later date).
  15. Time to set up the Serializers. This was... difficult. It took 2 days and two teachers to help me get this figured out. Because of the way that my system is set up you have treat each level you want out of the database as a collection of data.Alt TextAlt Text

  16. Set up the routes to these resources.
    Alt Text

  17. Before proceeding make sure that your seed data is correct.

Annnnndd this is getting too long. Time to have part 3 as I still need to set up my JWT.


References

  1. https://guides.rubyonrails.org/v2.3/getting_started.html
  2. https://www.codecademy.com/articles/what-is-cors
  3. https://stackoverflow.com/questions/1992019/how-can-i-rename-a-database-column-in-a-ruby-on-rails-migration
  4. https://github.com/cyu/rack-cors
Please Note that I am still learning. If something that I have stated is incorrect please let me know. I would love to learn more about what I may not understand fully.

Top comments (0)