Giter Site home page Giter Site logo

sinatra-user-auth's Introduction

User Authentication in Sinatra

Overview

In this codealong lab, we'll build a Sinatra application that will allow users to sign up for, log into, and then log out of your application.

Objectives

  1. Explain how logging in to an application stores a user's ID into a session hash
  2. Set up a root path and homepage for the application
  3. Build a user sign-up flow with a Users model that signs in and logs in a user
  4. Log out the user by clearing the session hash

User Authorization: Using Sessions

Logging In

What does it mean for a user to 'log in'? The action of logging in is the simple action of storing a user's ID in the session hash. Here's a basic user login flow:

  1. User visits the login page and fills out a form with their email and password. They hit 'submit' to POST that data to a controller route.
  2. That controller route accesses the user's email and password from the params hash. That info is used to find the appropriate user from the database with a line such as User.find_by(email: params[:email], password: params[:password]). Then, that user's ID is stored as the value of session[:user_id].
  3. As a result, we can introspect on the session hash in any other controller route and grab the current user by matching up a user ID with the value in session[:user_id]. That means that, for the duration of the session (i.e., the time between when someone logs in to and logs out of your app), the app will know who the current user is on every page.

A Note On Password Encryption

For the time being, we will simply store a user's password in the database in its raw form. However, that is not safe! In an upcoming lesson, we'll learn about password encryption: the act of scrambling a user's password into a super-secret code and storing a decrypter that will be able to match up a plaintext password entered by a user with the encrypted version stored in a database.

Logging Out

What does it mean to log out? Conceptually, it means we are terminating the session, the period of interaction between a given user and our app. The action of 'logging out' is really just the action of clearing all of the data, including the user's ID, from the session hash. Luckily for us, there is already a Ruby method for emptying a hash: #clear.

User Registration

Before a user can sign in, they need to sign up! What does it mean to 'sign up'? A new user submits their information (for example, their name, email, and password) via a form. When that form gets submitted, a POST request is sent to a route defined in the controller. That route will have code that does the following:

  1. Gets the new user's name, email, and password from the params hash.
  2. Uses that info to create and save a new instance of User. For example: User.create(name: params[:name], email: params[:email], password: params[:password]).
  3. Signs the user in once they have completed the sign-up process. It would be annoying if you had to create a new account on a site and then sign in immediately afterwards. So, in the same controller route in which we create a new user, we set the session[:user_id] equal to the new user's ID, effectively logging them in.
  4. Finally, we redirect the user somewhere else, such as their personal homepage.

Project Structure

Our Project

Our file structure looks like this:

-app
  |- controllers
      |- application_controller.rb
  |- models
      |- user.rb
  |- views
      |- home.erb
      |- registrations
          |- signup.erb
      |- sessions
          |- login.erb
      |- users
          |- home.erb
-config
-db
-spec
...

The app Folder

The app folder contains the models, views and controllers that make up the core of our Sinatra application. Get used to seeing this setup. It is conventional to group these files under an app folder.

Application Controller

  • The get '/registrations/signup' route has one responsibility: render the sign-up form view. This view can be found in app/views/registrations/signup.erb. Notice we have separate view sub-folders to correspond to the different controller action groupings.

  • The post '/registrations' route is responsible for handling the POST request that is sent when a user hits 'submit' on the sign-up form. It will contain code that gets the new user's info from the params hash, creates a new user, signs them in, and then redirects them somewhere else.

  • The get '/sessions/login' route is responsible for rendering the login form.

  • The post '/sessions' route is responsible for receiving the POST request that gets sent when a user hits 'submit' on the login form. This route contains code that grabs the user's info from the params hash, looks to match that info against the existing entries in the user database, and, if a matching entry is found, signs the user in.

  • The get '/sessions/logout' route is responsible for logging the user out by clearing the session hash.

  • The get '/users/home' route is responsible for rendering the user's homepage view.

The models Folder

The models folder is pretty straightforward. It contains one file because we only have one model in this app: User.

The code in app/models/user.rb will be pretty basic. We'll validate some of the attributes of our user by writing code that makes sure no one can sign up without inputting their name, email, and password. More on this later.

The views Folder

This folder has a few sub-folders we want to take a look at. Since we have different controllers responsible for different functions/features, we want our views folder structure to match up.

  • The views/registrations sub-directory contains one file, the template for the new user sign-up form. That template will be rendered by the get '/registrations/signup' route in our controller. This form will POST to the post '/registrations' route in our controller.
  • The views/sessions sub-directory contains one file, the template for the login form. This template is rendered by the get '/sessions/login' route in the controller. The form on this page sends a POST request that is handled by the post '/sessions' route.
  • The views/users sub-directory contains one file, the template for the user's homepage. This page is rendered by the get '/users/home' route in the controller.
  • We also have a home.erb file in the top level of the views directory. This is the page rendered by the root route, get '/'.

Part I: Models and Migrations

Our User model has a few attributes: a name, email, and password.

Step 1: Migration

Use rake db:create_migration to write a migration that creates a Users table with columns for name, email, and password. Run rake db:migrate SINATRA_ENV=test and then run your test suite.

You'll see that you're passing a number of tests, including these:

User
  is invalid without a name
  is invalid without a email
  is invalid without an password

Part II: Controllers and Views

Step 1: The Root Path and the Homepage

First things first, let's set up our root path and homepage.

Open up app/controllers/application_controller.rb and check out the get '/' route. This route should render the app/views/home.erb page with the following code:

erb :home

Run your test suite again with learn or rspec in the command line and you should be passing these two tests:

ApplicationController
  homepage: GET /
    responds with a 200 status code
    renders the homepage view, 'home.erb'

Start up your app by running shotgun in the terminal. Visit the homepage at localhost:9393. You should see a message that welcomes you to Hogwarts and shows you a link to sign up and a link to log in.

Let's look at the code behind this view. Open up app/views/home.erb and you should see the following:

<h1>Welcome to Hogwarts</h1>
<h4>Please sign up or log in to access your @hogwarts.edu email account</h4>
<a href="/registrations/signup">Sign Up</a>
<a href="/sessions/login">Log In</a>

Notice that we have two links, the "Sign Up" link and the "Log In" link. Let's take a closer look:

  • The 'href' (destination) value of the first link is /registrations/signup. This means that the link points to the get '/registrations/signup' route.
  • The 'href' value of the second link is /sessions/login. This means that the link points to the get '/sessions/login' route.

Let's move on to step 2, the building of our user sign-up flow.

Step 2: User Sign-up

In your controller you should see two routes dedicated to sign-up. Let's take a look at the first route, get '/registrations/signup', which is responsible for rendering the sign-up template. Add the following code in this route:

get '/registrations/signup' do
  erb :'/registrations/signup'
end

Navigate to localhost:9393/registrations/signup. You should see a page that says 'Sign Up Below:'. Let's make a sign-up form!

Open up app/views/registrations/signup.erb. Our signup form needs fields for name, email, and password. It needs to POST data to the '/registrations' path, so your form action should be '/registrations' and your form method should be POST.

Once you've written your form, go ahead and add the line puts params inside the post '/registrations' route in the controller. Then, fill out the form in your browser and hit the "Sign Up" button.

Hop on over to your terminal and you should see the params outputted there. It should look something like this (but with whatever info you entered into the form):

{"name"=>"Beini Huang", "email"=>"[email protected]", "password"=>"password"}

Okay, so we're inside our post '/registrations' route, and we have our params hash that contains the user's name, email, and password. Inside the post '/registrations' route, place the following code:

@user = User.new(name: params["name"], email: params["email"], password: params["password"])
@user.save

We did it! We registered a new user! Now we just need to sign them in. On the following line, set the session[:user_id] equal to our new user's ID:

session[:user_id] = @user.id

Take a look at the last line of the method:

redirect '/users/home'

Now that we've signed up and logged in our user, we want to take them to their homepage.

Go ahead and run the test suite again and you should see that almost all of the user sign-up tests are passing.

Step 3: Fetching the Current User

Open up the view file: app/views/users/home.erb and look at the following line of code:

"Welcome, <%=@user.name%>!"

Looks like this view is trying to operate on a @user variable. We know that the only variables that a view can access are instance variables set in the controller route that renders that particular view page. Let's take a look at the route in our controller that corresponds to the /users/home view.

Remember, after a user signs up and is signed in via the code we wrote in the previous step, we redirect to the '/users/home' path. Let's check out that route right now.

Again, take a look at the controller. You should see the get '/users/home' route. First, this route finds the current user based on the ID value stored in the session hash. Then, it sets an instance variable, @user, equal to that found user, allowing us to access the current user in the corresponding view page. Let's set it up:

get '/users/home' do
  @user = User.find(session[:user_id])
  erb :'/users/home'
end

Run the tests again and we should be passing all of our user sign up tests.

Step 4: Logging In

Go back to your homepage and look at the second of the two links:

<a href="/sessions/login">Log In</a>

This is a link to the get '/sessions/login' route. Checkout the two routes defined in the controller for logging in and out. We have a get '/sessions/login' route and a post '/sessions' route.

The get /sessions/login' route renders the login view page. Restart your app by executing Ctrl + C and then typing shotgun in your terminal. Navigate back to the root page, localhost:9393, and click on the 'Log In' link. It should take you to a page that says 'Log In Below:'. Let's create our login form!

Open up app/views/sessions/login.erb. We need a form that sends a POST request to /sessions and has input fields for email and password. Don't forget to add a submit button that says 'Log In'. Then, to test that everything is working as expected, place the line puts params in the post '/sessions' route. In your browser, fill out the form and hit 'Log In'.

In your terminal, you should see the outputted params hash looking something like this (but with whatever information you entered into the login form):

{"email"=>"[email protected]", "password"=>"password"}

Inside the post '/sessions' route, let's add the lines of code that will find the correct user from the database and log them in by setting the session[:user_id] equal to their user ID.

@user = User.find_by(email: params["email"], password: params["password"])
session[:user_id] = @user.id

Notice that the last line of the route redirects the user to their homepage:

redirect '/users/home'

We already coded the '/users/home' route in the controller to retrieve the current user based on the ID stored in session[:user_id].

What if our user doesn't provide the right email or password? What should our site show them next? Well, we should probably give them another shot at logging in. We can do so with a bit of conditional logic:

post '/sessions' do
  @user = User.find_by(email: params[:email], password: params[:password])
  if @user
    session[:user_id] = @user.id
    redirect '/users/home'
  end
  redirect '/sessions/login'
end

Run the test suite again and you should be passing the user login tests.

Step 5: Logging Out

Open up app/views/users/home.erb and check out the following link:

<a href="/sessions/logout">Log Out</a>

We have a link that takes us to the get '/sessions/logout' route, which is responsible for logging us out by clearing the session hash.

In the get '/sessions/logout' route in the controller, put:

session.clear

Run the test suite again, and you should be passing everything.

Conclusion

Phew! This was a big code-along, and we were introduced to some new concepts. Before moving on, play around with your app a bit. Practice signing up, logging out, and logging in, and get used to the general flow.

There's a lot to think about here, but here are a few takeaways:

  • Separate out your views into sub-folders according to their different concerns / controller routes.
  • Signing up for an app is nothing more than submitting a form, grabbing data from the params hash, and using it to create a new user.
  • Logging in is nothing more than locating the correct user and setting the :id key in the session hash equal to their user ID.
  • Logging out is accomplished by clearing all of the data from the session hash.

Another important takeaway from this lab is a general understanding of the flow of information between the different routes and views of an application. If you're still confused by the flow of signing up and logging in/out, try drawing it out. Can you map out where your web requests go from the point at which you click the "Sign Up" link all the way through until you log out and then attempt to log back in? Give it a shot.

sinatra-user-auth's People

Contributors

annjohn avatar aspenjames avatar bhollan avatar brennenawana avatar dalmaboros avatar danielseehausen avatar dfenjves avatar drakeltheryuujin avatar franknowinski avatar gj avatar ihollander avatar jd2rogers2 avatar karuna24s avatar maxwellbenton avatar meg-gutshall avatar mjdele avatar ngevan avatar pletcher avatar sgharms avatar sophiedebenedetto avatar victhevenot avatar zcodedoc avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sinatra-user-auth's Issues

Code-Along pre-completed

The code in app/controllers/application_controller.rb was already complete upon clone. The only coding left un-done was the forms in the views

Broken lab

Something is wrong with either the tests or the code provided. Unable to get past a failed test because the element "email" could not be found (see screenshot). This was part of the supposedly working base code that was provided. Attempted multiple times to correct, replaced every page of my code with the solution (except for the application_controller.rb file, which was inexplicably not 'solved'), and still could not get past that error.
screen shot 2017-07-03 at 6 07 25 pm

Codealong test left unpassed?

Hello,
When completing this codealong lab, it left one of the tests unsolved:

    it 'fails to log in with an incorrect password' do
      expect(current_path).to eq('/sessions/login')
      fill_in("email", :with => valid_user.email)
      fill_in("password", :with => "wrong")
      click_button('Log In')
      expect(current_path).to eq('/sessions/login')
    end

specifically, (# ./spec/features/user_feature_spec.rb:46) causes this failure:

  expected: "/sessions/login"
  got: "/sessions"

I was able to get the test to pass by checking with an if statement to make sure the computer had been able to find the correct User:

  post '/sessions' do
    @user = User.find_by(email: params["email"], password: params["password"])
    if @user == nil
      redirect '/sessions/login'
    else
      session[:id] = @user.id
      redirect '/users/home'
    end
  end

If your intention was to get students to figure it out on their own, it worked!
:)

db/migrate: Update File Name Required to Pass 1st Test

Hi,

To pass this first Step 1: Migration requires a _01 in front of the file name. Example: db/migrate/01_create_users_table.rb

I would not have intuited or thought of that. Over 1 hour to figure out and then with AAQ.

Please make it clearer in the lesson.


Step 1: Migration
Write a migration that creates a Users table with columns for name, email, and password. Run rake db:migrate SINATRA_ENV=test and then run your test suite.

You'll see that you're passing a number of tests, including these:

User
is invalid without a name
is invalid without a email
is invalid without an password

Validations

In Step 1: Migration, the section ends with "Let's think about the concept of validations..." Should there be more info about validations here? The rest of the lesson doesn't mention anything else about it. Thanks!

!codalong

Hi! So this lab was particularly frustrating for me because it starts out with "In this codealong lab..." and as I was following along, several things were not aligning with what the lab said. For instance

  1. When I came the user sign up, for step 2, I had to set up the form for logging in on step 4 first or simultaneously to get tests to pass.
  2. When I reached the end of the lab there was logic required for the post '/sessions' route to account for incorrect logins.
    The frustrating part is when the lab tells you the tests should be passing and they aren't and you have no idea what you did wrong when really something is missing/out of order.
    Removing the "codealong" at the beginning and snippets throughout would be helpful to prevent unnecessary frustrations!
    Thank you!

Apply Migrations To The Correct Database

There are two databases that come with this lab. It should probably be mentioned in the README that it is necessary to run rake db:migrate SINATRA_ENV=test in order to build the schema in the right database. If rake db:migrate is run like the README suggests, then it populates "user_authdevelopment.sqlite" database, but this one is not the one used by the specs.

Issues with codealong as well as the solution

The tests don't actually test for whether the session was cleared on logout, and the answer logout route doesn't clear the session either. This defeats the purpose of including it in the lab.

README Incorrect - session[:id] to session[:user_id]

Hi there,

Looks like the README needs to be updated in this lab. There are several times in the controller where 'session[:user_id]' is listed, but the README says to enter session[:id] in two different spots. I did so, following the README and it took a while to figure out that the README was just wrong and the code that came with the lab was actually correct. Seems like a simple fix that would save a bunch of folks a lot of time?

Thank you!
Rose

User tests don't match existing erb text

The existing text in the sign up and log in erb files should probably be updated to be capitalized so that it matches the Capybara tests. 'sign up' to 'Sign Up', 'log in' to 'Log In', etc.

Instance Variables In POST route

The lesson shows instance variables in the post '/sessions' controller route. Shouldn't these instance variables be local variables since post routes do not render views and thus do not need instance variables?

help

none of my frigging labs will run bundle install or learn submit and no one is able to help me

Error with Rake and rspec

Rake was not running correctly, so changed rakefile to:

require_relative './config/environment'
require 'sinatra/activerecord/rake'

rspec giving error of:

bundler: failed to load command: rspec (/usr/local/rvm/gems/ruby-2.3.1/bin/rspec)
NoMethodError: undefined method `needs_migration?' for ActiveRecord::Migrator:Class

new repository

good evening. I just deleted my repository to this lab as I was having a problem with the terminal on the version that I originally forked, and now I am unable to view the web page. I could use some help here please

The part of the README that discusses the Controller, needs to be re-written.

Hi. I noticed that the README is worded as though most of the code in the application_controller.rb file needs to be written by the student. However, the needed code in that Controller file is already there from the get-go.

Additionally, the post '/sessions' route has some extra code that isn't mentioned at all in the README, but it is needed to pass the tests.

Thirdly, near the end of "Step 4: Logging In", the README has a few lines of code, followed by this sentence: "Notice that the last line of the route redirects the user to their homepage." The problem with this is that, while the Controller has that last line of code mentioned above, the README does NOT.

I don't know if the code in the Controller should be left as is, or deleted so that students can code along, but the README needs to be re-written either way.

Thanks as always for looking into this!

---Sdcrouse

Rake db:create fails on Linux

Issue

When running on a local Linux Env or in the IDE, executing rake db:create is met with the following error:

[13:39:26] (master) sinatra-user-auth-v-000
// โ™ฅ rake db:create
WARNING: If you plan to load any of ActiveSupport's core extensions to Hash, be
sure to do so before loading Sinatra::Application or Sinatra::Base. If not,
you may disregard this warning.
rake aborted!
ActiveRecord::AdapterNotSpecified: 'development' database is not configured. Available: []
/home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/connection_adapters/connection_specification.rb:248:in resolve_symbol_connection' /home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/connection_adapters/connection_specification.rb:211:in resolve_connection'
/home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/connection_adapters/connection_specification.rb:139:in resolve' /home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/connection_adapters/connection_specification.rb:169:in spec'
/home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/connection_handling.rb:50:in establish_connection' /home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/tasks/database_tasks.rb:109:in create_current'
/home/aspen/.rvm/gems/ruby-2.3.7/gems/activerecord-4.2.0/lib/active_record/railties/databases.rake:17:in block (2 levels) in <top (required)>' /home/aspen/.rvm/gems/ruby-2.3.7/gems/rake-12.3.1/exe/rake:27:in <top (required)>'
/home/aspen/.rvm/gems/ruby-2.3.7/bin/ruby_executable_hooks:24:in eval' /home/aspen/.rvm/gems/ruby-2.3.7/bin/ruby_executable_hooks:24:in

'
Tasks: TOP => db:create
(See full trace by running task with --trace)

Replication

This was replicated on my instance of the IDE, as well as on my local machine running Ubuntu 18.10.
Attempted with Ruby versions 2.3.1, 2.3.3, and 2.3.7, all met with the same error.

Solution

The solution was creating an explicit database.yml file within the config directory. This is a fairly advanced issue and solution for students at this level of the curriculum, and should be acknowledged as moving from IDE to local environment is not advised until a later lesson.

Example database.yml file below:

development:
  adapter: sqlite3
  database: db/user_authdevelopment.sqlite
  pool: 5
  timeout: 5000

test:
  adapter: sqlite3
  database: db/user_authtest.sqlite
  pool: 5
  timeout: 5000

production:
  adapter: sqlite3
  database: db/user_authproduction.sqlite
  pool: 5
  timeout: 5000

#Staff

NoMethodError in config/spec files

I was getting the following error when running the rspec test suite:
NoMethodError: undefined method needs_migration?' for ActiveRecord::Migrator:Class`

I was able to find this chunk of code in config.ru and spec_helper.rb:

if defined?(ActiveRecord::Migrator) && ActiveRecord::Migrator.needs_migration?
  raise 'Migrations are pending run `rake db:migrate SINATRA_ENV=test` to resolve the issue.'
end

When I comment this chunk out, the labs run fine, as does all database functionality.

BigDecimal.new issue

/.rvm/gems/ruby-2.6.1/gems/activesupport-4.2.0/lib/active_support/core_ext/object/duplicable.rb:85: warning: BigDecimal.new is deprecated; use BigDecimal() method instead.

This error may be "harmless" but defeats the whole learn experience when you cant run tests via learn or learn --f-f

So many issues with this code along

Basically ran into issues with the test every step of the way. Im not even going to list them because it would take too long. It needs a complete fix.

@avidor Student unable to run `Rake db:migrate` as per lab instructions

With a fresh clone of the lab, student gets the following error when attempting to run migrate:

LoadError: cannot load such file -- active_record/railties/databases.rake

I attempted to manually create the database, but student still ran into issues using Rake commands. Student was able to work on other labs which used Rake to build DBs/create migrations, so I suspect this lab may have some faulty instructions/dependencies (noted in the previously raised issue for this lab).

Having Trouble running learn here

NoMethodError: undefined method needs_migration?' for ActiveRecord::Migrator:Class /home/shlokjoshi/sinatra-user-auth-cb-gh-000/spec/spec_helper.rb:8:in <top (required)>'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in require' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in block in requires='
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in each' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in requires='
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:112:in block in process_options_into' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in each'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in process_options_into' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:21:in configure'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:99:in setup' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:86:in run'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:71:in run' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:45:in invoke'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/exe/rspec:4:in <top (required)>' /usr/local/rvm/gems/ruby-2.3.1/bin/rspec:23:in load'
/usr/local/rvm/gems/ruby-2.3.1/bin/rspec:23:in `<top (required)>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.