GithubHelp home page GithubHelp logo

nyambati / express-acl Goto Github PK

View Code? Open in Web Editor NEW
227.0 12.0 51.0 1.34 MB

This is a express module that enables you to implement ACL with much ease

Home Page: https://nyambati.github.io/express-acl/

License: MIT License

JavaScript 98.04% Makefile 1.04% Dockerfile 0.92%

express-acl's Introduction

Express ACL

Build Status Coverage Status Codacy Badge Known Vulnerabilities

Express Access Control Lists (express-acl) enable you to manage the requests made to your express server. It makes use of ACL rules to protect your sever from unauthorized access. ACLs defines which user groups are granted access and the type of access they have against a specified resource. When a request is received against a resource, express-acl checks the corresponding ACL policy to verify if the requester has the necessary access permissions.

What are ACL rules

ACL is a set of rules that tell express-acl how to handle the requests made to your server against a specific resource. Think of them like road signs or traffic lights that control how your traffic flows in your app. ACL rules are defined in JSON or yaml syntax.

Important

Resources property has been changed from using string to routes, this change was made to support subrouting functionality, this means if your resource was users which gave access to all routes starting with users, it should be changed to users/*. The asterisk informs the package to match all the routes that starts with users. Resources also can include params i.e /users/:id this will match routes such as users/45, users/12, where 12 and 45 are considered :id section on the resource. More details can be found on the wiki

Example

[
  {
    "group": "user",
    "permissions": [
      {
        "resource": "users/*",
        "methods": ["POST", "GET", "PUT"],
        "action": "allow"
      }
    ]
  }
]

YAML syntax

- group: user
  permissions:
    - resource: users/*
      methods:
        - GET
        - POST
        - DELETE
      action: allow

The contents of this file will be discussed in the usage section

Installation

You can download express-acl from NPM

$ npm install express-acl

then in your project require express-acl

const acl = require('express-acl');

or GitHub

$ git clone https://github.com/andela-thomas/express-acl.git

copy the lib folder to your project and then require nacl.js

const acl = require('./lib/nacl');

Usage

Express acl uses the configuration approach to define access levels.

Configuration

First step is to create a file called nacl.json and place this in the root folder. This is the file where we will define the roles that can access our application, and the policies that restrict or give access to certain resources. Take a look at the example below.

[
  {
    "group": "admin",
    "permissions": [
      {
        "resource": "*",
        "methods": "*"
      }
    ],
    "action": "allow"
  },
  {
    "group": "user",
    "permissions": [
      {
        "resource": "users/",
        "methods": ["POST", "GET", "PUT"],
        "action": "deny"
      }
    ]
  }
]

In the example above we have defined an ACL with two policies with two roles, user and admin. A valid ACL should be an Array of objects(policies). The properties of the policies are explained below.

Property Type Description
group string This property defines the access group to which a user can belong to e.g user, guest, admin, trainer. This may vary depending with the architecture of your application.
permissions Array This property contains an array of objects that define the resources exposed to a group and the methods allowed/denied
resource string This is the route the permissions will be applied against. This property can be either * which applies to all routes, api/users which will apply permisstion to routes api/users or api/users/* which applies permission to all routes that prefix api/users
methods string or Array This are http methods that a user is allowed or denied from executing. ["POST", "GET", "PUT"]. use glob * if you want to include all http methods.
action string This property tell express-acl what action to perform on the permission given. Using the above example, the user policy specifies a deny action, meaning all traffic on route /api/users for methods GET, PUT, POST are denied, but the rest allowed. And for the admin, all traffic for all resource is allowed.
subRoutes Array This are permissions that should be used on subroutes of a specified prefix. It is helpfull when certain routes under a prefix requires different access definitions.

How to define effective ACL rules

ACLs define the way requests will be handled by express acl, therefore its important to ensure that they are well designed to maximize efficiency. For more details follow this link

Authentication

express-acl depends on the role of each authenticated user to pick the corresponding ACL policy for each defined user groups. Therefore, You should always place the acl middleware after the authenticate middleware. Example using jsonwebtoken middleware

// jsonwebtoken powered middleware
ROUTER.use(function(req, res, next) {
  const token = req.headers['x-access-token'];

  if (!token) {
    return next(new Error('No token Provided'));
  }

  jwt.verify(token, key, function(err, decoded) {
    if (err) {
      return res.send(err);
    }
    req.decoded = decoded;
    return next();
  });
});

// express-acl middleware depends on the the role
// the role can either be in req.decoded (jsonwebtoken)or req.session
// (express-session)

ROUTER.use(acl.authorize);

API

There are two API methods for express-acl.

config[type: function, params: config { filename,path, yml, encoding, baseUrl, rules}, response {}]

This methods loads the configuration json file. When this method it looks for nacl.json the root folder if path is not specified.

config

  • filename: Name of the ACL rule file e.g nacl.json
  • path: Location of the ACL rule file
  • baseUrl: The base url of your API e.g /developer/v1
  • rules: Allows you to set rules directly without using config file.
  • defaultRole : The default role to be assigned to users if they have no role defined.
  • decodedObjectName: The name of the object in the request where the role resides.
  • roleSearchPath: The path in which to look for the role within the req object
const acl = require('express-acl');

// path not specified
// looks for config.json in the root folder
// if your backend routes have base url prefix e.g  /api/<resource>,  v1/<resource> ,
// developer/v1/<resource>
// specify it in the config property baserUrl {baseurl: 'api'} ,
// {baseurl: 'v1'}, {baseurl: 'developer/v1'} respectively
// else you can specify {baseurl: '/'} or ignore it entirely

acl.config({
  baseUrl: 'api'
});

// path specified
// looks for ac.json in the config folder

acl.config({
  filename: 'acl.json',
  path: 'config'
});

// When specifying path you can also rename the json file e.g
// The above file can be acl.json or nacl.json or any_file_name.json

acl.config({
  rules: rulesArray
});

// When you use rules api, nacl will **not** to find the json/yaml file, so you can save your acl-rules with any Database;

// When you use rules api, nacl will **not** to find the json/yaml file, so you can save your acl-rules with any Database;

// The default role allows you to specify which role users will assume if they are not assigned any
acl.config({
  defaultRole: 'anonymous'
});

// By default this module will look for role in decoded object, if you would like to change the name of the object, you can specify this with decodedObjectName property.

// As per the example below, this module will look for req.user.role as compared to default req.decoded.role.

acl.config({
  decodedObjectName: 'user'
});

// You can also specify a deep path in which to look for the role, in case it's not inside the usual locations

acl.config({
  roleSearchPath: 'user.Role.name' //will search for role in req.user.Role.name
});

Response

This is the custom error you would like returned when a user is denied access to a resource. This error will be bound to status code of 403

const acl = require('express-acl');

let configObject = {
  filename: 'acl.json',
  path: 'config'
};

let responseObject = {
  status: 'Access Denied',
  message: 'You are not authorized to access this resource'
};

acl.config(configObject, responseObject);

Alternatively, you can pass a callback function in the config object. It will be called when a user is denied access to a resource. In this case, the responseObject will be ignored:

const acl = require('express-acl');

let configObject = {
  filename: 'acl.json',
  path: 'config',
  denyCallback: (res) => {
    return res.status(403).json({
      status: 'Access Denied',
      success: false,
      message: 'You are not authorized to access this resource'
    });
  }
};

acl.config(configObject);

authorize [type: middleware]

This is the middleware that manages your application requests based on the role and acl rules.

app.get(acl.authorize);

unless[type:function, params: function or object]

By default any route that has no defined policy against it is blocked, this means you cannot access this route until you specify a policy. This method enables you to exclude unprotected routes. This method uses express-unless package to achieve this functionality. For more details on its usage follow this link express-unless

//assuming we want to hide /auth/google from express acl

app.use(acl.authorize.unless({ path: ['/auth/google'] }));

Anytime that this route is visited, unless method will exclude it from being passed though our middleware.

N/B You don't have to install express-unless it has already been included into the project.

Example

Install express-acl

$ npm install express-acl

Create nacl.json in your root folder

[
  {
    "group": "user",
    "permissions": [
      {
        "resource": "users/*",
        "methods": ["POST", "GET", "PUT"],
        "action": "allow"
      }
    ]
  }
]

Require express-acl in your project router file.

const acl = require('express-acl');

Call the config method

acl.config({
  //specify your own baseUrl
  baseUrl: '/'
});

Add the acl middleware

app.use(acl.authorize);

For more details checkout the examples folder.

Partners

Spot the key metrics of your REST API at one glance with a single simple dashboard, set up alerts in 2 clicks and get notified of every problem immediately

Contributions

Pull requests are welcome. If you are adding a new feature or fixing an as-yet-untested use case, please consider writing unit tests to cover your change(s). For more information visit the contributions page

express-acl's People

Contributors

abdulrahman-khankan avatar adriwankenoby avatar bartduisters avatar darklam avatar dependabot[bot] avatar egorbenko avatar ela34 avatar filipdusek avatar gpgkd906 avatar hussainaliakbar avatar jabedhasan21 avatar mirza99 avatar nyambati avatar oofoamalu avatar ptxyz avatar sochix avatar tkasperczyk avatar zewa666 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

express-acl's Issues

Deny is not invoked when role is not provided as a string

Hi,
I found this bug in express-acl. I'm going to describe it below. Can you please let me know if this is a valid bug or not? i have fixed it as well and can make a PR for it as well if you want.

The issue:

Currently what happens is that if i set a role to any value with type integer or any other type (which is not a string) , express acl validates it in the authorize function with the following code:

if (!_.isString(role) || !role) return;

the !role condition will never be true because express-acl by default sets a role to guest if no role is provided at all. However the !_.isString(will be false) if the role is not provided as a string. But instead of calling the deny function, this simply returns ( not next() ) which is causing my application to get stuck. I think that this issue would persist for everyone because neither next is being called nor is the deny function.

I believe that in this case the deny function should be called with the error that the role is not provided as a string.

Like i said, i have already fixed this on my end. Happy to make a PR for it if you approve.

Thanks!

Resource name with hyphen (dash) throws "REQUIRED: Policy not found"

When url is set as ../user-roles or ../functional-areas i.e. with a hyphen (dash)

and permission set as;

{
    "resource": "job-roles",
    "methods": [
        "GET"
    ],
    "action": "allow"
},
{
    "resource": "functional-areas",
    "methods": [
        "GET"
    ],
    "action": "allow"
}

the request returns with following error:

{"status":"Access denied","success":false,"message":"REQUIRED: Policy not found"}

If the same is changed to: ../user_roles or ../functional_areas it works properly.

Any idea why?

Identity Based Access Control

As mentioned here:

Typical example: users can edit their own comments but can only read other users comments. So having a role that either grants or deny edit permissions to the resource comment/edit is not good enough. The permission depends on which comment the user is accessing.

Other example here:

Let me give you an example based on a blogging platform where a writer can create a blog post and then open it up for editing — should the writer role also allow to rewrite every post in the system? Probably not. We need to first check if they are the owner of the post.

Is there a way to achieve that?

Returning Status code 403

Response
This is the custom error you would like returned when a user is denied access to a resource. This error will be bound to status code of 403

returns 401, why?

lib/index.js file contains

if (!permission) {
    return res.status(401).json(deny(options.customMessage, options.response));
}

Npm dependency

Hi,
There is a npm dependency in the package.json file.
I'm wondering if it's necessary to keep it.

Dynamic roles based on database.

Hello,
a quick question. I have all ACLs in my DB and based on logged in user I have different roles (based on many conditions).
Is it possible to pass dynamically a rules object or even better use some attribute like: rulesObjectName etc. to pass from where rules should be applied ?

Thank you in advance for your answer

User defined as non-guest in DB, ACL only sees 'guest' role

Trying to add this to my existing express application. I set up the webapp using this configuration:

webapp.js

let configObject = {
		filename: 'nacl.json',
		path: 'config'
	};
 
	let responseObject = {
		status: 'Access Denied',
		message: 'You are not authorized to access this resource'
	};

	acl.config(configObject, responseObject);
	app.use(acl.authorize);

nacl.json

[
  {
    "group": "user",
    "permissions": [
      {
        "resource": "pages/all",
        "methods": ["POST", "GET", "PUT"],
        "action": "allow"
      }
    ]
  }
]

Inside my controller I am setting up the router as such:

router.use(function(req, res, next) {
	let token = req.headers['authorization'].replace('Bearer ', '');

	if (token) {
		jwt.verify(token, '18DXStreet!', function(err, decoded) {
			if (err) {
				console.log(err);
				return res.send(err);
			}
			req.decoded = decoded;
			next();
		});
	}
});

router.use(acl.authorize);

And the endpoint I am trying to access:

router.get('/all', passport.authenticate('jwt', { session: false }), async function(req, res) {

	let pages = await Page.find({}, {'__v': false}).sort({ name: 1 });
	res.json({pages: pages});
});

The JWT attached to the user is defined in the database as { role: user }, however the application returns:

{
    "status": "Access denied",
    "success": false,
    "message": "REQUIRED: Policy for role guest is not defined"
}

Unsure why this is occurring, would love some additional insight as to how to integrate this into my app.

ES6 import syntax

in a TS project

import acl from 'express-acl';

and also

import * as acl from 'express-acl';

return error "declaration file not found"

Can rules be cascaded?

Is it possible to have cascading rules on the same resource?
Like having a rule that explicitly denies all methods, then other rules that explicitly allow a few. This would mean that the same method has multiple rules defined for it but the system can resolve the one that has final effect, maybe through priorities, ordering, etc.

roleSearchPath config doesn't work!

Hello!

I set roleSearchPath but this config is doesn't work.
acl.config({ filename: 'nacl.json', roleSearchPath: 'user.role' });

//express-acl/lib/common.js
objectPath.get(req, searchPath) //undefined

But searchPath set is correct 'user.role'

Example req.user: { "profile": { "gender": "", "location": "", "name": "", "website": "" }, "tokens": [], "things": [], "_id": "", "email": "", "password": "", "role": "user" }

Unprotected path

Is there anywhere to omit certain route from authorization. For example I would not want protect the /auth path.

Can I do like:

app.use(acl.authorize).unless({path: ['/auth']}));

Access is denied if query parameter is present.

const permission = findPermissionForRoute(

originalUrl being passed through as route for findPermissionForRoute function includes the query parameters. Unless you explicitly have a policy to match against the query parameter and it's value exactly, access will be denied as no permissions will be found for the path.

ACL group keeps using default

ACL keeps using access control permissions for my default group (anonymous) even though the user is logged in and belongs to another group/role.

What can I do to fix this? Thanks.

Can you clarify the need for baseUrl

Hi,
I have read the documentation and would like a clarification on something:
If I want to make acl work for all my 'api'-prefixed routes I would need to add

acl.config({
    baseUrl: 'api',
   // other configurations...
})

and every request will be allowed or denied based on my configuration file (nacl.yml/nacl.json), right?

But in my current situation routes that are not starting with 'api' have response (for example /auth/register)

{
  "status": "Access denied",
  "success": false,
  "message": "REQUIRED: Policy not found"
}

I thought that only routes matching the baseUrl will be checked by the plugin...

Changing error message?

How can I change the error message for 403 forbidden?

{"success":"error","message":"Access denied"}

I tried this in express app, but the above message get return before hitting the below code:

app.use(function(err, req, res, next) {
  res.status(err.status || 403);
  res.status(403).send(err.message);
  next(err);
});

Default config file path is module path

The config file per default is searched inside the module dir, which will fail miserably. This also forces implementations to use absolute paths.

Failing example:

/* roles.js */
import acl from 'express-acl'

acl.config({
    yml: true,
    filename: 'roles.yml',
})

Working example:

/* roles.js */
import acl from 'express-acl'

acl.config({
    yml: true,
    path: __dirname,
    filename: 'roles.yml',
})

IMHO the default should be the pwd or other project related root path.

Permissions on routes rather than on resources

Is there a possible way to give permission to an access group on routes. The routes can be dynamic too.

For example:

nacl.json looks like:

[{ "group": "user", "permissions": [{ "resource": "fans/:id/size", "methods": [ "POST", "GET", "PUT" ], "action": "allow" }] }]
This does not work until I change resource to "resource": "fans"

And if this is not possible do we have to extend the package?

Issue when using with AWS cognito

I am having trouble trying to use this library with AWS cognito. I have multiple roles for a test user and it doesnt seem to work.

Please could you assist.

Thankyou

Issue with ACL evaluation

I think (at least from my point a view) there is a logic issue in the way ACLs are evaluated. Given the ACL below, if I connect to "api/version" using GET, I get an error.
From my understanding the ACL below should not reject this action.

	{
		"group": "guest",
		"permissions": [
			{
				"resource": "*",
				"methods": ["OPTIONS"],
				"action": "allow"
			},
			{
				"resource": "/api/version/*",
				"methods": "*",
				"action": "allow"
			},
              ]
       }

This can be fixed by changing the code in 'common.js' around line 184 to something like:

    if (matchUrlToResource(route, resource)) {
      if (isAllowed(method, permission))
      	return permission;
    }
 

In fact resource evaluation should continue until there is no more chance an 'allow' is found, this is consistent with the fact that'deny' is the default action.
What do you think?

Provide way to persist rules in database.

Objective

This feature will enable storing of ACL configuration rules in a database for persistence. This will make the configuration rules portable and easy to manage if used in multiple apps.

Permission check API

Is there any API or function that I can use to check if the user has the right to access the page before making API request?

For example, I have a SPA, it can be written on Angular, React or Vuejs. To prevent a user from accessing a page to POST a new sales, I would like to request an API call to my server to check if the user has permission to the page, so that I can disable the page from loading.

Check permissions

I need to implement a method to validate ACL through ajax, it would be great if something like this is implemented, for example:

const checkACL = {resource: 'post', methods: ['GET']};
acl.check(req, checkACL);

decodedObjectName and searchPath does not allow to map custom role property

Hi
I am using the role propery in my session as req.session.user.role. But As the doc says by default it search the role either req.decoded or req.session. To mach the custom location we can use decodedObjectName searchPath.

I have tried different combinations but still no luck. If explicitly I make the role accessible via req.session.role. It works. But I want to change it to req.session.user.role.

How to achieve this?

Thanks.

Support of multiple roles

Hi,

I'm new to this library, so might be wrong, but I see that "role" is a single value string.
I guess there no built-in solution for that but what's the best way to support multiple roles for user?

E.g. that "req.decoded.role" will be an array of roles.

Thanks!
Elad.

Deny on resource causes "Policy not found" issue.

I’m exploring ACL solutions for a Node.js project and express-acl felt like the right choice. I installed it with npm and the first part of integration and just having a simple allow-everything admin user went pretty well. Then for the next user group I wanted to add restrictions for certain routes but seem to have run in to trouble with it. Hopefully this is just a pilot error on my part.

This is what my simple nacl.json looks like :

[
   {  
      "group":"admin",
      "permissions":[  
         {  
            "resource":"*",
            "methods":"*",
            "action":"allow"
         }
      ]
   },
   {  
      "group":"user1",
      "permissions":[  
         {  
            "resource":"admin",
            "methods":"*",
            "action":"deny"
         }
      ]
   }
]

There are no errors on startup and I want the user1 profile to have access to everything except for routes starting with “admin”. Things are fine if I just have one “allow” permissions entry (like for admin) but when I start specifying “deny” or multiple rules, it seems to have trouble parsing the json (?). I get the following response for a resource:

{"status":"Access denied","success":false,"message":"REQUIRED: Policy not found”}

It seems to complain about not being able to find the ‘user1’ policy group. I’ve seen the problem trying to use “deny” on a resource or while trying to use multiple permissions entries. I’m using Node.js v6.11.3 on MacOSX.

Thank you.

ACL matching issue

I'm using the ACL file below.
If I have a JWT with role set to '3p' and the route I'm trying to access is '/api/4p/login' then I'm authorized to access this route.
My understanding is that I should not be authorized. Is it an issue with my ACL?

[
	{
		"group": "3p",
		"permissions": [
			{
				"resource": "/api/3p/*",
				"methods": "*",
				"action": "allow"
			}
		]
	},
	{
		"group": "4p",
		"permissions": [
			{
				"resource": "/api/4p/*",
				"methods": "*",
				"action": "allow"
			}
		]
	},
]

Unable to deny subRoutes

I'm trying to do something like this, however video/categories remains accessible. Am I doing something wrong?

{
     "resource": "video/*",
     "methods": "*",
     "action": "allow",
     "subRoutes" : [
	{
		"resource": "categories",
		"methods": "*",
		"action": "deny"
	}
     ]
}

Unable to use it as middleware

@nyambati . I liked the simplicity of this package. However I have an issue when I try to use it as a middleware within a route. For example, please find attached code:
express-acl-issue.txt

When I try to to reach the route that I don't want user's to reach per the permissions defined in acl.json, I am still getting the data back. Expected result would be to receive status code 403 and status message of 'Access Denied'. From looking at my code could you please let me know if I am doing anything wrong here.

Thank you in advance.

[Feature request] Give us more control over the deny behaviour

Hello,

Currently, when a user cannot access a certain URI (when your findPermissionForRoute function returns false), the res's status code is set to 401:

express-acl/index.js:

  const permission = findPermissionForRoute(
    req.originalUrl,
    req.method,
    options.baseUrl,
    policy
  );

  if (!permission) {
    return res.status(401).json(deny(options.customMessage, options.response));
  }

It would be cool if we had more control over this behaviour. My proposition: add an additional option which would allow us to pass a callback function. The callback would be executed when the permission constant is undefined or false, as shown below:

  ...
  if (!permission) {
      if (typeof options.denyCallback === 'function'){
          return options.denyCallback(res);
      } else {
          return res.status(401).json(deny(options.customMessage, options.response));
      }
  }

No base url

/**
   * Now lets include our router to the main app
   * Make sure that your app has the base url, e.g. /api/ or /v1
   * nacl will detect your resource based on this url.
   */

What if I prefer no base url?

Restrict access to certain subroutes under main route

Assume : Following are the 2 routes in express APP:

  1. GET /user/:user_id
  2. GET /user/:user_id/approve

I want to give access to route no 1 to system admin but route no 2 to super admin only. How can I achieve that with this library?

I have version 1.0.0 installed on my system, I reviewed the code of Module. I think, if I will allow GET USER permission to any user, user will be able to access all child routes under user endpoint.

Convert Codebase Linter from JsHint to Eslint

Problem

The current codebase uses Jshint linter which does not work well with ES6 configuration. With Node 8 LTS Approaching, we may need to update the codebase to supported ES6 functionalities to shake off some of the modules currently being used e.g Lodash.

Solution

Convert the current Linting configuration to use Eslint with Airbnb styleguide.

Always return status code 200

In lib/common.js
const checkIfHasAccess = ( method, res, next, permission, customMessage, response ) => { if (isAllowed(method, permission)) { return next(); } return res.json(deny(customMessage, response)); };

I alway get status 200 because of this line
return res.json(deny(customMessage, response));
it should be replaced by this
return res.status(403).json(deny(customMessage, response));

Is this project alive?

I'm trying to find any acl package for express application, found this one but it looks that here not so much activity since 2018. Is this project alive?

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.