Coder Social home page Coder Social logo

mongoose-auth's Introduction

mongoose-auth

User authentication plugin for mongoose node.js orm.

mongoose-auth enables you to support authorization in any number of ways via authorization strategies.

An authorization strategy is how you authorize your user. Currently mongoose-auth supports the following authorization strategies:

  • password
  • facebook
  • twitter
  • github
  • instagram
  • google

mongoose-auth does 3 things:

  1. Schema decoration
  2. (optional) Drop in routing for connect apps.
  3. (optional) Dynamic helpers for express apps.

It integrates the everyauth module to help it take care of the routing and helpers. everyauth is a general purpose npm module for authentication & authorization that can be used independently of mongoose.

Schema Decoration

As you add successive authorization strategies, mongoose-auth at a bare minimum augments your schema with typed attributes corresponding to parameters related to your chosen authorization strategies. For example, if facebook is one of your authorization strategies, then it will add attributes to your User Schema such as 'fb.id' and 'fb.email'.

To decorate your schema:

    var mongoose = require('mongoose')
      , Schema = mongoose.Schema
      , mongooseAuth = require('mongoose-auth');
    
    var UserSchema = new Schema({});
    UserSchema.plugin(mongooseAuth, {
      facebook: true
    });

Beyond Schema Decoration: Routing

Applications require more than just User Schema augmentation in order to implement a complete authorization strategy. Applications also need routes exposing the one or more steps involved for a given authorization strategy. Moreover, applications each handle in their own unique way how they want to respond to successful or failed logins (in addition to logout handling). If you are not using a connect, then you will have to set all of this up yourself. In this case, mongoose-auth only provides you with Schema decoration.

But, if you are building your app on top of connect, then mongoose-auth provides drop in solutions for you. Here is how you can get access to the routing that mongoose-auth provides. Not the "STEP X: ..." comments:

    var mongoose = require('mongoose')
      , Schema = mongoose.Schema
      , mongooseAuth = require('mongoose-auth');
    
    var UserSchema = new Schema({})
      , User;
   
    // STEP 1: Schema Decoration and Configuration for the Routing
    UserSchema.plugin(mongooseAuth, {
        // Here, we attach your User model to every module
        everymodule: {
          everyauth: {
              User: function () {
                return User;
              }
          }
        }
        
      , facebook: {
          everyauth: {
              myHostname: 'http://localhost:3000'
            , appId: 'YOUR APP ID HERE'
            , appSecret: 'YOUR APP SECRET HERE'
            , redirectPath: '/'
          }
        }
    });
   
    mongoose.model('User', UserSchema);

    mongoose.connect('mongodb://localhost/example');

    User = mongoose.model('User');

    var app = express.createServer(
        express.bodyParser()
      , express.static(__dirname + "/public")
      , express.cookieParser()
      , express.session({ secret: 'esoognom'})
      
        // STEP 2: Add in the Routing
      , mongooseAuth.middleware()

        // IMPORTANT!!!!!!! Do not add app.router, to your middleware chain 
        // explicitly, or you will run into problems accessing `req.user`
        // i.e., do not use app.use(app.router). Let express do this for you
        // automatically for you upon your first app.get or app.post.
    );
   
    // STEP 3: Add in Dynamic View Helpers (only if you are using express)
    mongooseAuth.helpExpress(app);

    app.listen(3000);

View Helpers and Convenience Methods & Getters

In "Step 3" of the last code sample, we are adding dynamic view helpers, for if you are using the Express web framework. This automically gives you access to a convenient everyauth local variable from your view, so you do not have to pass req as a local to your view:

  • everyauth.loggedIn - a Boolean getter that tells you if the request is by a logged in user
  • everyauth.user - the mongoose User document associated with the session
  • everyauth.facebook - The is equivalent to what is stored at req.session.auth.facebook, so you can do things like ...
  • everyauth.facebook.user - returns the user json provided from the OAuth provider.
  • everyauth.facebook.accessToken - returns the access_token provided from the OAuth provider for authorized API calls on behalf of the user.
  • And you also get this pattern for other modules - e.g., everyauth.twitter.user, everyauth.github.user, etc.

You also get access to the view helper

  • user - the same as everyauth.user above

As an example of how you would use these, consider the following ./views/user.jade jade template:

.user-id
  .label User Id
  .value #{user.id}
.facebook-id
  .label User Facebook Id
  .value #{everyauth.facebook.user.id}

The "STEP 2: Add in the Routing" step in the last code sample also provides convenience methods on the ServerRequest instance req. From any scope that has access to req, you get the following convenience getter and method:

  • req.loggedIn - a Boolean getter that tells you if the request is by a logged in user
  • req.user - the mongoose User document associated with the session
  • req.logout() - clears the sesion of your auth data

Using Multiple Authorization Strategies at Once

You can also use multiple authorization strategies in the same application. Here is an example, using 5 authorization strategies:

    // A configuration file for holding all of your
    // 3rd party OAuth credentials
    var conf = require('./conf');
    UserSchema.plugin(mongooseAuth, {
        // Here, we attach your User model to every module
        everymodule: {
          everyauth: {
              User: function () {
                return User;
              }
          }
        }
      , facebook: {
          everyauth: {
              myHostname: 'http://localhost:3000'
            , appId: conf.fb.appId
            , appSecret: conf.fb.appSecret
            , redirectPath: '/'
          }
        }
      , twitter: {
          everyauth: {
              myHostname: 'http://localhost:3000'
            , consumerKey: conf.twit.consumerKey
            , consumerSecret: conf.twit.consumerSecret
            , redirectPath: '/'
          }
        }
      , password: {
            everyauth: {
                getLoginPath: '/login'
              , postLoginPath: '/login'
              , loginView: 'login.jade'
              , getRegisterPath: '/register'
              , postRegisterPath: '/register'
              , registerView: 'register.jade'
              , loginSuccessRedirect: '/'
              , registerSuccessRedirect: '/'
            }
        }
      , github: {
          everyauth: {
              myHostname: 'http://localhost:3000'
            , appId: conf.github.appId
            , appSecret: conf.github.appSecret
            , redirectPath: '/'
          }
        }
      , instagram: {
          everyauth: {
              myHostname: 'http://localhost:3000'
            , appId: conf.instagram.clientId
            , appSecret: conf.instagram.clientSecret
            , redirectPath: '/'
          }
        }
    });

Example

There is an example app located in ./example. To run it:

$ cd example
$ node server.js

Then navigate to http://localhost:3000/

Recipe 1: Linking Multiple Account Logins Together

A common recipe is allowing a user to login via multiple accounts and to link those accounts under one user document.

This can be done in the following way:

The real magic lies with https://github.com/bnoguchi/everyauth/, and it should be more obvious once I document everyauth more and document mongoose-auth's relationship to everyauth.

In everyauth's design, every auth module is defined as a set of steps, which are exposed in such a way for you to over-ride. The step that is of particular interest for this scenario is the findOrCreateUser step required by every everyauth module. mongoose-auth defines a default version of this findOrCreateUser step for each everyauth auth module it supports (You can find these default definitions in "lib/modules/#{moduleName}/everyauth.js" -- e.g., see .lib/modules/facebook/everyauth.js).

So for example, this is how you would over-ride the default findOrCreateUser step for the facebook module if you are using both the facebook and password module:

UserSchema.plugin(mongooseAuth, {
  facebook: {
    everyauth: {
        myHostname: ...
      , ...
      , findOrCreateUser: function (session, accessTok, accessTokExtra, fbUser) {
          var promise = this.Promise()
              , User = this.User()();
          User.findById(session.auth.userId, function (err, user) {
            if (err) return promise.fail(err);
            if (!user) {
              User.where('password.login', fbUser.email).findOne( function (err, user) {
                if (err) return promise.fail(err);
                if (!user) {
                  User.createWithFB(fbUser, accessTok, accessTokExtra.expires, function (err, createdUser) {
                    if (err) return promise.fail(err);
                    return promise.fulfill(createdUser);
                  });
                } else {
                  assignFbDataToUser(user, accessTok, accessTokExtra, fbUser);
                  user.save( function (err, user) {
                    if (err) return promise.fail(err);
                    promise.fulfill(user);
                  });
                }
              });
            } else {
              assignFbDataToUser(user, accessTok, accessTokExtra, fbUser);
              
              // Save the new data to the user doc in the db
              user.save( function (err, user) {
                if (err) return promise.fail(err);
                promise.fuilfill(user);
              });
            }
          });
        });
        return promise; // Make sure to return the promise that promises the user
      }
  }
});

// Assign all properties - see lib/modules/facebook/schema.js for details
function assignFbDataToUser (user, accessTok, accessTokExtra, fbUser) {
  user.fb.accessToken = accessTok;
  user.fb.expires = accessTokExtra.expires;
  user.fb.id = fbUser.id;
  user.fb.name.first = fbUser.first_name;
  // etc. more assigning...
}

As this is a common recipe, I plan on adding support for this into everyauth and mongoose-auth, so it's more drop-in, and developers do not have to add this custom code themselves. The intent is for common things like this to be invisible to the developer, so it just works like magic. So, in the near future, you won't have to over-ride the findOrCreateUser step every time you want this feature. This will be coming soon.

Recipe 2: Configuring Email or Phone to be your Login for the Password Module

By default, everyauth and therefore mongoose-auth use the attribute login as the default attribute used for logging in with the password module.

However, the need can arise to use a different attribute (such as email) that implies a different schema (use email: String instead of login: String) in addition to different validation assumptions (email validations are more strict that login handle validations).

Luckily, mongoose-auth provide support for this out of the box. All you need to do is (look for the line labeled "THIS NEXT LINE IS THE ONLY ADDITION"):

UserSchema.plugin(mongooseAuth, {
    // Here, we attach your User model to every module
    everymodule: {
      everyauth: {
          User: function () {
            return User;
          }
      }
    }
  , password: {
        // THIS NEXT LINE IS THE ONLY ADDITION
        loginWith: 'email' // Or loginWith: 'phone'

      , everyauth: {
            getLoginPath: '/login'
          , postLoginPath: '/login'
          , loginView: 'login.jade'
          , getRegisterPath: '/register'
          , postRegisterPath: '/register'
          , registerView: 'register.jade'
          , loginSuccessRedirect: '/'
          , registerSuccessRedirect: '/'
        }
    }
});

Automatically, mongoose-auth will use an email String attribute in your User schema instead of the default login String attribute. Moreover, it will automatically add in validation checks to make sure that the email is valid before registering a user through the registration process of the password module.

Recipe 3: Extra password registration data besides login + password

Sometimes your registration will ask for more information from the user besides the login and password.

For this particular scenario, you can configure extraParams.

UserSchema.plugin(mongooseAuth, {
    // Here, we attach your User model to every module
    everymodule: {
      everyauth: {
          User: function () {
            return User;
          }
      }
    }
  , password: {
        extraParams: {
            phone: String
          , name: {
                first: String
              , last: String
            }
        }

      , everyauth: {
            getLoginPath: '/login'
          , postLoginPath: '/login'
          , loginView: 'login.jade'
          , getRegisterPath: '/register'
          , postRegisterPath: '/register'
          , registerView: 'register.jade'
          , loginSuccessRedirect: '/'
          , registerSuccessRedirect: '/'
        }
    }
});

What this effectively does is:

  1. Adds phone, name.first, and name.last as attributes to your UserSchema.
  2. Automatically extracts the registration parameters after a visitor submits the registration form and saves them to a new User document. The registration form <input> names should be, e.g., in the example above: 'phone', 'name[first]', and 'name[last]'.

Please see ./example/server.js for a live example.

Recipe 4: Adding more attributes to your schema

This one ha come up enough that it is here as a recipe, even though it is not specific to mongoose-auth. Suppose you want to add a special attribute such as roles: [String] to your UserSchema. This is something that you can do using just mongoose

var UserSchema = new mongoose.Schema({
    roles: [String]
  , // other custom attributes
});

UserSchema.plugin(mongooseAuth, {
  // mongooseAuth *adds* other attributes to your UserSchema
  // depending on the auth modules you choose.
});

Recipe 5: Customizing how you do password login authentication

Currently, mongoose-auth does password authentication by login and password. Suppose you also want to authenticate by checking against an additional parameter, like active, which is a Boolean attribute on your UserSchema that indicates whether this user has been activated or not. Then you can modify the authenticate everyauth step in the following way:

var UserSchema = new Schema({
  active: Boolean
}), User;
UserSchema.plugin(mongooseAuth, {
    everymodule: {
      everyauth: {
          User: function () {
            return User;
          }
      }
    }
  , password: {
        loginWith: 'email' 
      , everyauth: {
            getLoginPath: '/login'
          , postLoginPath: '/login'
          , loginView: 'login.jade'
          , getRegisterPath: '/register'
          , postRegisterPath: '/register'
          , registerView: 'register.jade'
          , loginSuccessRedirect: '/'
          , registerSuccessRedirect: '/'
   
            // WHAT YOU ADD IS THE FOLLOWING:
            // The logic is adapted from the default authenticate
            // implementation in lib/modules/password/everyauth.js
          , authenticate: function (login, password) {
              var promise
                , errors = []; 
              if (!login) errors.push('Missing login.');
              if (!password) errors.push('Missing password.');
              if (errors.length) return errors;

              promise = this.Promise();
              this.User()().authenticate(login, password, function (err, user) {
                if (err) {
                  errors.push(err.message || err);
                  return promise.fulfill(errors);
                }   
                if (!user) {
                  errors.push('Failed login.');
                  return promise.fulfill(errors);
                }
                
                // The following block is the new code
                if (!user.active) {
                  errors.push('You are not yet activated.');
                  return promise.fulfill(errors);
                }
                
                promise.fulfill(user);
              });
              return promise;
            }
        }
    }
});
mongoose.model('User', UserSchema);

User = mongoose.model('User');

Recipe 6: Customizing logout handler

This is a copy of instructions from everyauth and applied to mongoose-auth:

// ...
UserSchema.plugin(mongooseAuth, {
  everymodule: {
    everyauth: {
      User: function () {
        return User;
      },
      handleLogout: function(req, res) {
        // Put your extra logic here
        req.logout(); // The logout method is added for you by everyauth, too
        // And/or put your extra logic here
        res.writeHead(303, { 'Location': this.logoutRedirectPath() });
        res.end();
      }
    }
  }
  // ...
});
// ...

License

MIT License


Author

Brian Noguchi

mongoose-auth's People

Contributors

bnoguchi avatar niftylettuce avatar oost avatar rajivnavada avatar turbo87 avatar

Stargazers

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

Watchers

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

mongoose-auth's Issues

Twitter auth problem

I'm having a problem with the twitter auth on my site if someone clicks the link "click here to continue" while twitter is redirecting. In such a case the URL is the same as if they allowed twitter to redirect automatically, but the server has an empty response and then nothing loads.

Waiting for twitter to automatically redirect works exactly as expected (but I can't make people wait)

Any ideas?

it won't work when express.session({ secret: 'esoognom'}) in app.use() to configure express app.

I'm a newbie of express.js dev and also node.js
So I wonder whether this would be a bug of mongoose-auth .

I follow the examples in the git repo like follwing,it works perfect.

var app = module.exports = express.createServer(
    express.bodyParser()
  , express.static(__dirname + "/public")
  , express.cookieParser()
  , express.session({ secret: 'esoognom'})
);

but when I use configure, the req.sess in the mongooseAuth.middleware() (I trace it to everyauth.middleware()) is undifined.

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'esoognom'}));
  app.use(app.router);
});

Would it be a bug?

Install Error On "mongoose-types" Dependency

When installing via NPM, I get an error: "Required package: mongoose-types(>=1.0.3) not found."

If I install mongoose-types via npm first, I am then able to install mongoose-auth without issue.

Here's the full log:
npm install mongoose-auth npm info it worked if it ends with ok npm info using [email protected] npm info using [email protected] npm info preinstall [email protected] npm ERR! install failed Error: Required package: mongoose-types(>=1.0.3) not found. npm ERR! install failed (required by: [email protected]) npm ERR! install failed at /usr/local/lib/node/.npm/npm/0.3.18/package/lib/build.js:185:27 npm ERR! install failed at cb (/usr/local/lib/node/.npm/npm/0.3.18/package/lib/utils/graceful-fs.js:31:9) npm info install failed rollback npm info uninstall [ '[email protected]' ] npm info preuninstall [email protected] npm info uninstall [email protected] npm info auto-deactive not symlink npm info postuninstall [email protected] npm info uninstall [email protected] complete npm info install failed rolled back npm ERR! Error: Required package: mongoose-types(>=1.0.3) not found. npm ERR! (required by: [email protected]) npm ERR! at /usr/local/lib/node/.npm/npm/0.3.18/package/lib/build.js:185:27 npm ERR! at cb (/usr/local/lib/node/.npm/npm/0.3.18/package/lib/utils/graceful-fs.js:31:9) npm ERR! Report this *entire* log at <http://github.com/isaacs/npm/issues> npm ERR! or email it to <[email protected]> npm ERR! Just tweeting a tiny part of the error will not be helpful. npm ERR! System Darwin 10.6.0 npm ERR! argv { remain: npm ERR! argv [ 'mongoose-auth', npm ERR! argv 'bcrypt@>=0.2.0', npm ERR! argv 'mongoose@>=1.2.0', npm ERR! argv 'everyauth@>=0.0.9' ], npm ERR! argv cooked: [ 'install', 'mongoose-auth' ], npm ERR! argv original: [ 'install', 'mongoose-auth' ] } npm not ok

Twitter not working?

I can't seem to get twitter to authenticate. It gets back to the homepage with a url string but goes no further. No errors or anything. Github works though...

Facebook error: You have not defined a path for the route alias postLoginPath.

When using the Facebook module, I get the following error:

Error: You have not defined a path for the route alias postLoginPath.
at Object.routeApp (/usr/lib/node/.npm/everyauth/0.0.9/package/lib/everymodule.js:173:19)
at Function.<anonymous> (/usr/lib/node/.npm/everyauth/0.0.9/package/index.js:38:41)
at Function.router (/usr/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:94:6)
at Function.middleware (/usr/lib/node/.npm/everyauth/0.0.9/package/index.js:33:15)
at HTTPServer.<anonymous> (/Users/jason/Sites/tixelated/app.js:77:20)
at HTTPServer.configure (/Users/jason/node_modules/.npm/express/2.0.0/package/lib/http.js:422:8)
at Object.<anonymous> (/Users/jason/Sites/tixelated/app.js:46:5)
at Module._compile (module.js:383:26)
at Object..js (module.js:389:10)
at Module.load (module.js:315:31)

Invocation:

var UserSchema = new Schema({
  username         : String,
  first_name       : String,
  middle_name      : String,
  last_name        : String,
  type             : Number,
  admin            : Number                                                                                                                                                    
});
UserSchema.plugin(useTimestamps);
UserSchema.plugin(mod_mongooseAuth, {
  facebook : { everyauth : settings.everyauth.facebook }
});

Configs (settings.everyauth.facebook):

{
  appId           : 'xxxxxxxxxxxxxx'
  , appSecret     : 'xxxxxxxxxxxxxxxxxxx'
  , scope         : 'email'
  , redirectPath  : '/'
  , entryPath     : '/auth/facebook'
  , callbackPath  : '/auth/facebook/callback'
}

registration error

Hey Brian, I'll look into it later on to see if I can fix, but wanted to send you this right away, just in case you knew about it already.

$ node example/server.js
starting step - displayRegister
starting step - extractLoginPassword
...finished step
starting step - registerUser

/mongoose-auth/node_modules/.npm/everyauth/0.1.6/package/lib/sequence.js:90
throw err;
^
Error: Step registerUser of password module timed out.
at /mongoose-auth/node_modules/.npm/everyauth/0.1.6/package/lib/sequence.js:105:18
at Object. (/mongoose-auth/node_modules/.npm/everyauth/0.1.6/package/lib/promise.js:62:27)
at Timer.callback (timers.js:83:39)

Linkedin and Google login

Is it currently possible to use google/linkedin with mongoose-auth? I noticed they are on the everyauth docs, is it just a matter of configuring them?

Cannot register with password authentication

When attempting to use the password authentication (using the example application provided with module after removing loginWith: 'email' line), the following error occurs:

TypeError: Cannot read property 'sanitize' of undefined
at Object._validateRegistrationBase (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/modules/password.js:284:40)
at Object.exec (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/step.js:48:21)
at /home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/stepSequence.js:19:38
at [object Object].callback (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/promise.js:13:12)
at RouteTriggeredSequence._bind (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/stepSequence.js:18:20)
at RouteTriggeredSequence.start (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/stepSequence.js:45:33)
at RouteTriggeredSequence.routeHandler (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/lib/routeTriggeredSequence.js:16:13)
at Object. (native)
at nextMiddleware (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/node_modules/connect/lib/middleware/router.js:175:25)
at param (/home/ryan/git/mongoose-auth/node_modules/mongoose-auth/node_modules/everyauth/node_modules/connect/lib/middleware/router.js:183:16)

Create and confirming account before saving

Hi Brian, I need some help with this scenario. Its a user first visit to my app and he login with FB user, at this point I would like to redirect the user to register screen where he can create a name, last name, user name(his email) and a password, he would need to type it, I can use FB to populate the first and last name and the username based on email, and let the user to choose if he really want that email address as login. In the example that you have for linking accounts, it assumes that the user is already created, but in this case I am creating a user based on FB account and would like the user to confirm before saving. Is there an easy way to do this interruption and not having to do it in a after screen.

Thank you in advance for your help!

JB

Error: You have not defined a path for the route alias getLoginPath.

I'm testing a node.js app I'm writing when I get the following error. I'm not sure what to do about it since there' nothing in the example. I suspect the error is on my side since I'm so new to node.
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: You have not defined a path for the route alias getLoginPath.
at Object.routeApp (/home/levi/Projects/Cloudrr/node_modules/mongoose-auth/node_modules/everyauth/lib/modules/everymodule.js:240:19)
at Function. (/home/levi/Projects/Cloudrr/node_modules/mongoose-auth/node_modules/everyauth/index.js:56:19)
at Function.router (/home/levi/Projects/Cloudrr/node_modules/mongoose-auth/node_modules/everyauth/node_modules/connect/lib/middleware/router.js:96:6)
at Object.middleware (/home/levi/Projects/Cloudrr/node_modules/mongoose-auth/node_modules/everyauth/index.js:50:15)
at Function.middleware (native)
at Object. (/home/levi/Projects/Cloudrr/app.js:12:20)
at Module._compile (module.js:411:26)
at Object..js (module.js:417:10)
at Module.load (module.js:343:31)
at Function._load (module.js:302:12)

my app.js, models.js, and package.json are available at https://gist.github.com/1294116
Thank you for your time.

Timeouts?

Hi, how can I set the timeout for mongoose-auth?I can't seem to figure it out.

login should be validated for uniqueness

Can workaround by adding User.path('login').index({ unique: true }); after the User.plugin(mongooseAuth ... stuff and then handling the duplicate key errors. It'd be nice if this was built in by default.

Connecting multiple accounts

Hey :) GREAT WORK!

Is it possible to connect multiple accounts to the one user? I'm thinking if their email matches they can be merged, or if the user is logged in, then it automatically connects/merges rather than creating a new user.

Thoughts?

populate everyauth.user

Im using expres and i have defined extra param for user
houses: [{ type: Schema.ObjectId, ref: 'Property', required: false}]
now i would need to populate this by calling .populate('houses') and i need to do it for every page to my active user, so i could call everyauth.user.house[i].name for example in my views. So my question - where should correctly put this populate? If it wouldnt be needed in every page i would put it in my controller, but since its needed everywhere i would like to extend everyauth express helper.

FB id is been saved to the email field after loggedin

Here is what I get after a login, you will notice the code bellow from the collection output.

 "email": "fb: 100000647911219" 

Also the email address shouldn't be saving any value since its optional when using facebook or other strategies, but required when using pasword or adding profile info after logged-in with facebook for instance.

This is the output after loggedin

{
   "_id": ObjectId("4dc07411cbf9defd1a000008"),
   "fb": {
     "name": {
       "last": "Brumley",
       "first": "Jonathan",
       "full": "Jonathan Eushell Brumley" 
    },
     "updatedTime": "2011-05-02T03: 31: 20+0000",
     "verified": true,
     "locale": "en_US",
     "timezone": "-6",
     "gender": "male",
     "alias": "jobrumley",
     "expires": "Wed, 31 Dec 1969 18: 00: 05 -0600",
     "accessToken": "180675088648545|2.GpF7_O_6a9AcUVCwjgTwPQ__.3600.1304463600.1-100000647911219|pmoWGfQK8lC-4ADfrewOSAiYW-0",
     "id": "100000647911219" 
  },
   "email": "fb: 100000647911219" 
}

Thank you Brian!
JB

recipe 1

it looks like in the example you are giving (dual login fb + password)
you need to test first that session.auth.userId exist or this will throw a Cannot read property 'userId' of undefined

node 0.6.0 segmentation fault

I'm not sure what is causing this but I'm seeing it in 0.6.0 and 0.6.1. I have a pretty simple app using mongoose auth and when trying to login node exits with nothing but "Segmentation fault."

lib / modules / password / index.js note

In the following code, if some one was to use loginWith: login the code needlessly calls delete schema.login;.
In another note should we absolutely be confined to value being of type String?

Object.defineProperty(exports, 'specialOptHandlers', {
    value: {
        loginWith: function (value) {
          if (value) {
            delete schema.login;
            schema[value] = { type: String, unique: true };
            everyauth.password.loginWith(value);
          }
        }...

Suddenly unable to register new users

Session data looks OK. Here it is.

{ data: {
      "lastAccess":1310210912086
     ,"cookie":{
          "originalMaxAge":14400000
         ,"expires":"2011-07-09T15:28:32.683Z"
         ,"httpOnly":true
         ,"path":"/"
       }
     ,"flash":{}
  },
  _id: 4e1836543c79656dd465fc59,
  sid: '4kX7OEk3Jo4IZ9xICMaMZZKv.7tkCXX+0ZPQg3Y56SOtCgx5W2ZgVdWBP4+MQ8lUKFts',
  expires: Sat, 09 Jul 2011 15:28:32 GMT }

And here's the console log...
starting step - extractLoginPassword
...finished step
starting step - extractExtraRegistrationParams
...finished step
starting step - aggregateParams
...finished step
starting step - validateRegistrationBase
...finished step
starting step - validateRegistration
...finished step
starting step - maybeBreakToRegistrationFailSteps
...finished step
starting step - registerUser
{ stack: [Getter/Setter],
arguments: undefined,
type: undefined,
message: 'E11000 duplicate key error index: dev.users.$login_1 dup key: { : null }' }
...finished step
starting step - extractUserOrHandleErrors
breaking out to registrationFailSteps
starting step - respondToRegistrationFail
...finished step

Can't register any new users. Bit of a headache! I'm trying to track down the relevant loc myself but if you have any tips I'd really appreciate.

Thanks for all the hard work Brian

TypeError: Object function String() { [native code] } has no method 'get'

I keep on getting this error when i try to include mongoose-auth and then use the password plugin:

TypeError: Object function String() { [native code] } has no method 'get'
at /site/node_modules/mongoose-auth/lib/modules/password/plugin.js:35:30
at /site/node_modules/mongoose-auth/index.js:73:5
at Array.forEach (native)
at plugin (/site/node_modules/mongoose-auth/index.js:36:6)
at Schema.plugin (/site/node_modules/mongoose/lib/mongoose/schema.js:289:3)
at Object. (/site/site/models/Users.js:27:7)
at Module._compile (module.js:407:26)
at module.js:413:10
at Object..js (/usr/local/lib/node_modules/node-dev/wrapper.js:59:5)
at Module.load (module.js:339:31)

any clues on what is causing this?

Removing app.router causes problems

Removing app.router as suggested in the configuration instructions in the README seems to break routing in general for express. Is it possible that this instruction is incorrect or outdated?

Error: Step findOrCreateUser of `facebook` module timed out.

The whole error is as follows

Error: Step findOrCreateUser of `facebook` module timed out.
at /home/dotcloud/node_modules/everyauth/lib/step.js:119:18
at Object.<anonymous> (/home/dotcloud/node_modules/everyauth/lib/promise.js:65:27)
at Timer.callback (timers.js:83:39)

This is from my staging env hosted on dotcloud. On my local it runs fine. When checking npm list for version numbers, I found that some of the everyauth submodules were higher version than what was on my local. (Everyauth version was the same).

Local: (not sure why connect-redis is there)

├─┬ [email protected] 
│ ├─┬ [email protected] 
│ │ ├─┬ [email protected]  extraneous
│ │ │ └── UNMET DEPENDENCY redis >= 0.0.1
│ │ ├── [email protected] 
│ │ └── [email protected] 
│ ├── [email protected] 
│ ├── [email protected] 
│ ├── [email protected] 
│ └─┬ [email protected] 
│   └── [email protected] 

dotcloud:

├─┬ [email protected] 
│ ├─┬ [email protected] 
│ │ ├── [email protected] 
│ │ └── [email protected] 
│ ├── [email protected] 
│ ├── [email protected] 
│ ├── [email protected] 
│ └─┬ [email protected] 
│   └── [email protected] 

Would the different versions have anything to do with the error? I overrode findOrCreateUser so could it be a problem with my code, even if it works on my local? I'm pretty new to node, so a push in the right direction would be a big help :)

Thanks!

View Helpers everyauth.user.id and user.id Not working

When logged in via Twitter, the view helper everyauth.twitter.user.id works. However, the other two mentioned in the title (as seen in the documentation area Express Helpers) cause an error: "Cannot read property 'id' of undefined"

Edit: Sorry, wrong project. Embarrassing.

Problem using email in password authorization strategy

Hi,

I'm trying to use the password authorization strategy with an email field instead of the login field.
I've added the following code to my schema js file but it does not work.

var UserSchema = new Schema({
        email  : { type: String, index: { unique: true}}
        , password  : String
  }), User;
UserSchema.plugin(mongooseAuth, {
    // Here, we attach your User model to every module
    everymodule: {
      everyauth: {
          User: function () {
            return User;
          }   
      }   
    }   
    , password: {
          // THIS NEXT LINE IS THE ONLY ADDITION
          loginWith: 'email' // Or loginWith: 'phone'

        , everyauth: {
              getLoginPath: '/login'
            , postLoginPath: '/login'
            , loginView: 'login.jade'
            , getRegisterPath: '/register'
            , postRegisterPath: '/register'
            , registerView: 'register.jade'
            , loginSuccessRedirect: '/' 
            , registerSuccessRedirect: '/' 
          }   
      }   
}); 
mongoose.model('User', UserSchema);

When I try to start the server I get always the error bellow:

node.js:134
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
TypeError: Object function String() { [native code] } has no method 'get'
    at /.../node_modules/mongoose-auth/lib/modules/password/plugin.js:35:30
    at /.../node_modules/mongoose-auth/index.js:73:5
    at Array.forEach (native)
    at plugin (/.../node_modules/mongoose-auth/index.js:36:6)
    at Schema.plugin (/.../node_modules/mongoose/lib/mongoose/schema.js:277:3)
    at Object.make (/.../database_schema.js:50:13)
    at Object.<anonymous> (/.../controllers/main.js:6:36)
    at Module._compile (module.js:404:26)
    at Object..js (module.js:410:10)
    at Module.load (module.js:336:31)

Can you please tell me if I'm doing something wrong or if this a bug in the plugin.

Thanks.
Best regards,
Migrate

Uploading files

Hi!
I'm using the password module of Mongoose Auth for an application that requires the user to upload a file in the register process.
I'm trying to upload the file to Mongo (there must be small files) adding a field in extraParams.
The problem is that instead of uploading the raw file to the DB it only writes the filename and not its contents.
I think accessing the request parameters and getting the input's value will work as expected.
So my question is: can I access request parameters from extraParams?
For example:

extraParams: {
  file: {type: Buffer, default: req.params.fileToUpload.contents}
}

Thanks,
Luis

How to override authentication

Hi,

I have an active flag in my User model and would like to allow only active users to be able to successfully login but I don't know how to do this. I've tried to follow http://stackoverflow.com/questions/5800996/i-got-mongoose-auth-to-work-but-how-do-i-do-some-custom-stuff-to-it but it didn't work.
Here is the code.

var UserSchema = new Schema({
    // actor id related with the user.
    actor_id  : ObjectId
}), User;
UserSchema.plugin(useTimestamps);
UserSchema.plugin(mongooseAuth, {
    everymodule: {
      everyauth: {
          User: function () {
            return User;
          }
      }
    }
    , password: {
        loginWith: 'email' 
      , everyauth: {
            getLoginPath: '/login'
          , postLoginPath: '/login'
          , loginView: 'login.jade'
          , getRegisterPath: '/register'
          , postRegisterPath: '/register'
          , registerView: 'register.jade'
          , loginSuccessRedirect: '/'
          , registerSuccessRedirect: '/'
          , authenticate: function (login, password) {
              console.log("authenticate!!!");
              var promise = this.Promise();
              User.find({ email: login, password: password, active: 1}, function (err, user) {
                  if (err) return promise.fulfill([err]);
                 promise.fulfill(user);
               });
               return promise;
          }
        }
    }
});
mongoose.model('User', UserSchema);

User = mongoose.model('User');

but it does seem not work. The server takes too much time to call the authentication method (more than 3 minutes) and returns nothing to the browser.

Can you please help me?

Thanks.
Best regards,
Migrate

'mongoose-types' dependency?

Looks like there's a dependency declaration missing from package.json? I'm getting the following error after requiring "mongoose-auth":

node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Cannot find module 'mongoose-types'
at Function._resolveFilename (module.js:320:11)
at Function._load (module.js:266:25)
at require (module.js:348:19)
at Object. (/usr/local/lib/node/.npm/mongoose-auth/0.0.5/package/lib/modules/facebook/schema.js:2:21)
at Module._compile (module.js:404:26)
at Object..js (module.js:410:10)
at Module.load (module.js:336:31)
at Function._load (module.js:297:12)
at require (module.js:348:19)
at Object. (/usr/local/lib/node/.npm/mongoose-auth/0.0.5/package/lib/modules/facebook/index.js:1:80)

everyauth is not defined

I've attempted installing mongoose-auth in one of my projects, but haven't managed to figure out how to resolve the "everyauth is not defined" template error that I get when attempting to duplicate a simpler version of your included example in my own project. I'm also unable to get the drop in routes for /login and /register working, they just 404.

I'm still rather new at node.js, so this is likely not a mongoose-auth issue but a problem of my own making—I likely have something simple misconfigured or some other such issue that I've not quite grasped yet. Still, I'd really like to understand the problem and learn from it, so if you could point me in the right direction I'd be very appreciative.

My project (an express app) is here, and after running the server.js file, you should be able to see the template error by going to http://localhost:8081/.

Thanks in advance for your help!

Can't override findOrCreateUser ?

Thanks for building this module, I really like! But I've ran into a prob.

This may not be a bug, as I think I'm just inexperienced.
Anyway, I want to over-ride findOrCreateUsers, because I want to assign each new user a random "code" upon signup, and put it inside their db.users profile as a field, "code".

I read the documentation, and saw that you could override findOrCreateUser. So I did that:

//Begin User Login----------------
var UserSchema = new Schema({}), User;
var Promise = everyauth.Promise;
UserSchema.plugin(mongooseAuth,{
        everymodule: {
          everyauth: {
              User: function () {
                return User;
              }   
          }   
        }   
      , facebook: {
          everyauth: {
                myHostname: settings.fb.hostname,
                appId: settings.fb.fbAppId,
                appSecret: settings.fb.fbSecret,
                scope: settings.fb.fbScope,
                entryPath: "/account/facebook/auth",
                redirectPath: '/account/prep',
                findOrCreateUser: function (sess, accessTok, accessTokExtra, fbUser) {
                    var promise = new Promise(), self = this;
                    this.User()().findOne({'fb.id': fbUser.id}, function (err, foundUser) {
                      if (foundUser)
                        return promise.fulfill(foundUser);
                      self.User()().createWithFB(fbUser, accessTok, accessTokExtra.expires, function (err, createdUser) {
                        return promise.fulfill(createdUser);
                      }); 
                    }); 
                    return promise;
                }   
        }   
    }   
}); 
mongoose.model("User", UserSchema);
var User = mongoose.model("User")
//End User Login--------------------

I copied and pasted what was in "mongoose-auth/lib/facebook/" into my app.js. (above, you see the copied code).

Everything works, and I'm able to login/create a user!! However, the only problem is that after the redirectPath, "req.user" is undefined. "req.loggedIn" says it's true, but req.user is undefined.

Twitter auth not working

I've successfully got Facebook logins working however Twitter auth is not.
The first phase of the oAuth seems to be working just fine but when twitter comes back with the oauth_token and oauth_verifier the app seems to be completely ignoring that. No debug logs from everyauth at all.

Here's my twitter config:

    twitter: {
      everyauth: {
        myHostname: 'http://wmd.local:3000',
        consumerKey: conf.twit.consumerKey,
        consumerSecret: conf.twit.consumerSecret,
        redirectPath: '/'
      }
    }

Let me know if there's any other info I can share that might be helpful here.

facebook auth error

@bnguchi:
The example in example folder works fine with Twitter and github auth. Facebook auth comes with the error:
-- An error occurred with everyauth node.js example. Please try again later.

Catch exception on timeout

Hi - I often get this error when authenticating with facebook:

Error: Step getAccessToken of `facebook` module timed out.
    at /usr/local/tixelated/node_modules/mongoose-auth/node_modules/everyauth/lib/step.js:101:18
    at Object.<anonymous> (/usr/local/tixelated/node_modules/mongoose-auth/node_modules/everyauth/lib/promise.js:63:27)
    at Timer.callback (timers.js:62:39)

I've read the advice about increasing the timeout value, but am looking for some advice on the recommended way to catch this exception (more of a node question than auth question I guess.) It crashes node entirely when it occurs...

NPM Install Fails

I just tried to install mongoose-auth via NPM and received this error. Have you seen this issue before?

npm info uninstall [email protected] complete
npm info uninstall [email protected] complete
npm info uninstall [email protected] complete
npm info uninstall [email protected] complete
npm info uninstall [email protected] complete
npm info install failed rolled back
npm ERR! Error: [email protected] install: node-waf configure build
npm ERR! sh "-c" "node-waf configure build" failed with 1
npm ERR! at ChildProcess. (/usr/local/lib/node/.npm/npm/0.3.15/package/lib/utils/exec.js:49:20)
npm ERR! at ChildProcess.emit (events.js:45:17)
npm ERR! at ChildProcess.onexit (child_process.js:171:12)
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the bcrypt package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-waf configure build
npm ERR! You can get their info via:
npm ERR! npm owner ls bcrypt
npm ERR! There is likely additional logging output above.
npm ERR! System Darwin 11.1.0
npm ERR! argv { remain:
npm ERR! argv [ 'mongoose-auth',
npm ERR! argv 'bcrypt@>=0.2.0',
npm ERR! argv 'mongoose@>=1.4.0',
npm ERR! argv 'everyauth@>=0.2.11',
npm ERR! argv 'mongoose-types@>=1.0.3',
npm ERR! argv 'oauth@>=0.9.0',
npm ERR! argv 'restler@>=0.2.1',
npm ERR! argv 'connect@>=1.4.0',
npm ERR! argv 'openid@=0.1.8',
npm ERR! argv 'xml2js@>=0.1.7',
npm ERR! argv 'mongoose@>= 1.0.16',
npm ERR! argv 'sax@>=0.1.1' ],
npm ERR! argv cooked: [ 'install', 'mongoose-auth' ],
npm ERR! argv original: [ 'install', 'mongoose-auth' ] }
npm not ok

mongoose-auth and connect-form

Hi,

I have an upload form that works fine, but when I add mongoose-auth it stops working. The "req.form.complete" is never called and the server hangs. Can you please help me?

Code: https://gist.github.com/1006435
Note: Upload function is change_image

Thanks again.
Best regards,
Migrate

Step registerUser of `password` module timed out.

I'm trying out mongoose-auth and I get this error:

127.0.0.1 - - [Fri, 16 Sep 2011 13:44:07 GMT] "GET /register HTTP/1.1" 200 772 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"
{ stack: [Getter/Setter],
arguments: undefined,
type: undefined,
message: 'Step registerUser of password module timed out.' }
Error: Step registerUser of password module timed out.
at /Users/Alfred/Sites/note0/node_modules/mongoose-auth/node_modules/everyauth/lib/step.js:121:18
at Object. (/Users/Alfred/Sites/note0/node_modules/mongoose-auth/node_modules/everyauth/lib/promise.js:65:27)
at Timer.callback (timers.js:83:39)

Know what it could be?

Access to User db object

Hey there - wondering how to get access to the actual DB User record that's linked to the facebook/twitter/etc account info. That is, once a user logs in (using, say, facebook,) I know I can get at their facebook info from req.session.auth.facebook, but not that actual user record.

I just wanted to check and make sure there isn't a way already built to do this before getting into querying for that user record via the facebook embedded document, which is otherwise the only way I know how to do it...

has no method 'middleware'

I can't get mongoose-auth to work with my Express server:

var app = express.createServer(
  mongooseAuth.middleware()
)

I get the output of the entire mongoose-auth file and then it says "has no method 'middleware'". I get the same thing when I try to access helpExpress() from within the node REPL.

Am I missing something? I went through the README several times and can't see where I may have gone wrong.

log debug

Hi thks for this super useful project
Just a quick question, logs work fine when I clone the project and run the demo from the example folder
but if I copy the folder rename var mongooseAuth = require('../index'); to var mongooseAuth = require('mongoose-auth');
and install the dependency via npm the auth steps are not logged anymore

Unable to authenticate with twitter

hi Brian, for some reason I am unable to authenticate with twitter, I keep getting the Authorize app screen on twitter, even if I click on Authorize,

this is my twitter everyauth setup

, twitter: {
      everyauth: {
          //callbackPath: '/users',
          myHostname: 'http://localhost.com:3000'
        , consumerKey: 'xxxxxxxx'
        , consumerSecret: 'xxxxxxxxx'
        , redirectPath: '/users'
      }
    }/*

consumer key and secret is ok I already verified it.

This is the debug output

starting step - getRequestToken
...finished step
starting step - storeRequestToken
...finished step
starting step - redirectToProviderAuth
...finished step
starting step - getRequestToken
...finished step
starting step - storeRequestToken
...finished step
starting step - redirectToProviderAuth
...finished step

I am able to authenticate with facebook with no problem. I am using everyauth 0.2.4 and mongoose auth 0.0.9

Any ideas?

Thanks!

password module: cannot override extractExtraRegistrationParams

The Problem

The change to index.js in commit e7108009316a51aa809e087f3307ceb8c7a8071b - namely the addition of specialOptHandlers - means there is no clear way override the extractExtraRegistrationParams step. On the README you do it like so:

      , everyauth: {
            getLoginPath: '/login'
          , postLoginPath: '/login'
          , loginView: 'login.jade'
          , getRegisterPath: '/register'
          , postRegisterPath: '/register'
          , registerView: 'register.jade'
          , loginSuccessRedirect: '/'
          , registerSuccessRedirect: '/'

            // These are the NEW lines
          , extractExtraRegistrationParams: function (req) {
              return {
                  phone: req.body.phone
                , name: {
                      first: req.body.first_name
                  }
              };
            }

... but this doesn't actually work anymore, as the definition of extractExtraRegistrationParams is overwritten by the specialOpt recursion version.

Why is this a problem?

Auto-recursion means you cannot whitelist/blacklist user input. If a user adds a field to a form before submitting (via FireBug or whatever) it will then automatically be mapped by the recursive implementation of extractExtraRegistrationParams and saved to the database.

req.user is undefined though everything appears to be working

Hey Brian,

I'm running into a confusing issue. I've got a feeling it's a everyauth issue but I'm using mongooseAuth so I'm positing it here.

Everything is working fine for logging in and creating users. I can login via twitter or the password module and things seem to be working fine. The only issue is that is that req.user is undefined. I could just set this myself but since I know it's supposed to do this I wanted to let you know.

Here is my model code:
https://github.com/mattmcmanus/statusQuo/blob/express-mongoose/models.js#L11

I'm running express 2.3.12, everyauth 0.2.12, mongoose-auth 0.0.11

Please let me know if there is anything else you need. I'm not sure what else to give you at this point.

Login with email

Hi Brian, I am currently working on an application where the User model will be highly used to store medical records and locations, User can login with facebook or twitter and then create an account with email, phone, first name and last name, so if user is logged in with FB they will be prompted to create an account with the fields above however if the user doesnt have twitter or facebook they will need to register an account with above fields(username would the email) plus a password for login.

Currently login is the default key for the username, but instead of login I would like to use email, so user can logon just with their email. Is their an easy way to do this change.

What is the best way to add more fields to the build in registration, so for example I would like to add firstName, lastName and Phone?. Do I need to create my own registration or is there a way to overwrite the default and use mine way of registering.

Any good suggestion to handle the above scenario?

Thank you for such a great node module.

TypeError: Object function plugin (schema, opts)

I'm quite positive I'm doing something wrong, but I'm using the basic vanilla example code and getting the following output:

 throw e; // process.nextTick error, or 'error' event on first tick
        ^
TypeError: Object function plugin(schema, opts) {
  if (Object.keys(opts).length === 0)
    throw new Error('You must specify at least one module.');

  // Make sure to flag everymodule, so that we
  // run the everyauth defaults for everymodule later
  opts.everymodule || (opts.everymodule = true);

  moduleLoadOrder.filter( function (moduleName) {
    return moduleName in opts;
  }).forEach( function (moduleName) {
    var _module = Modules[moduleName];
    if (!_module)
      throw new Error("Missing module named " + moduleName);

    var decorateSchema = _module.plugin;

    var moduleOpts = opts[moduleName];
    if (moduleOpts === true) {
      moduleOpts = {};
    }

    var everyauthConfig = moduleOpts.everyauth || {};

    // Module specific defaults for everyauth
    var everyauthDefaults = _module.everyauth;
    for (var k in everyauthDefaults) {
      if (!everyauthConfig[k])
        everyauthConfig[k] = everyauthDefaults[k];
    }

    // Configure everyauth for t

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.