Giter VIP home page Giter VIP logo

django-authtools's Introduction

django-authtools

Build Status

A custom user model app for Django 2.2+ that features email as username and other things. It tries to stay true to the built-in user model for the most part.

Read the django-authtools documentation.

Quickstart

Before you use this, you should probably read the documentation about custom User models.

  1. Install the package:

    $ pip install django-authtools
  2. Add authtools to your INSTALLED_APPS.
  3. Add the following to your settings.py:

    AUTH_USER_MODEL = 'authtools.User'
  4. Enjoy.

django-authtools's People

Contributors

acatton avatar alanjds avatar bashu avatar bgaudino avatar cdunn6754 avatar fundor333 avatar gavinwahl avatar gcaprio avatar glarrain avatar ivanvenosdel avatar jackton1 avatar jorgecarleitao avatar julianandrews avatar jxcl avatar mexicat avatar pidelport avatar pilate avatar rockymeza avatar scaredcat avatar weslord 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-authtools's Issues

Where are the templates?

We need a place to host some good default templates for the log in stuff. We can provide some, but it's going to be hard to support everybody's block structures, so they might just serve as examples.

I think it might be possible to make these templates work for maybe a quarter of people if they extend from base.html and then only put stuff in block content, but they will never be a universal solution.

New release with Django 1.8 support

Hello!

I see where the Django 1.8 support got merged back in July, but a release has not been shipped to PyPi that includes it. v1.2 comes down with pip install django-authtools, which doesn't function in 1.8.

It's not a problem to pin the install in requirements.txt to the GitHub branch for now, but is there a plan to push that out soon?

Thanks!

Extra migration is created in Django 1.8

A third migration gets created on django 1.8. Need to either add that migration to authtools, or fix the initial migration so the extra migration is not created. The reason the migration is created is because the help_text on User.groups "changed".

In the initial migration it is:

'The groups this user belongs to. A user will get all permissions granted to each of their groups'

But on the User model it is actually:

'The groups this user belongs to. A user will get all permissions granted to each of their groups.'

(just missing a period on the end)

PasswordChangeView doesn't handle session auth hashes

1.7 added the ability to have the session authenticated by a hash of user details; see here:

https://github.com/django/django/pull/2494/files#diff-7

I think PasswordChangeView's form_valid could do with a call to update_session_auth_hash to ensure changing the password doesn't log the user out before they even get to the PasswordChangeDoneView.

For now, the following workaround seem to suffice:

class CustomPasswordChangeView(PasswordChangeView):
    def form_valid(self, form):
        result = super(CustomPasswordChangeView, self).form_valid(form)
        update_session_auth_hash(self.request, form.user)
        return result

error while installing django-authtools

Hi, i'm trying since a couple of days to install the package via pip3 in a venv in my "test" machine powered by archlinux.
I get this error msg:

(py3env) [kaddour@archlinux edge]$ pip3 install django-authtools
    Collecting django-authtools
  Using cached django-authtools-1.2.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 20, in <module>
      File "/tmp/pip-build-m5e6ar3z/django-authtools/setup.py", line 23, in <module>
        long_description='\n\n'.join([read('README.rst'), read('CHANGES.rst')]),
      File "/tmp/pip-build-m5e6ar3z/django-authtools/setup.py", line 10, in read
        return open(os.path.join(os.path.dirname(__file__), fname)).read()
      File "/usr/lib/python3.4/encodings/ascii.py", line 26, in decode
        return codecs.ascii_decode(input, self.errors)[0]
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 721: ordinal not in range(128)

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-m5e6ar3z/django-authtools                            

I believe it has to do with encoding, using ascii instead of utf8
Any help is welcome !

Signature of create_superuser() not allways compatible with Django's own

I am trying to write a pytest test of one of my views that requires a logged-in admin user and I'm using the pytest-django admin_client fixture for that.

This fails as follows:

        try:
            user = UserModel._default_manager.get(**{username_field: username})
        except UserModel.DoesNotExist:
            extra_fields = {}
            if username_field not in ("username", "email"):
                extra_fields[username_field] = "admin"
            user = UserModel._default_manager.create_superuser(
>               username, "[email protected]", "password", **extra_fields
            )
E           TypeError: create_superuser() takes 1 positional argument but 4 were given

../.virtualenvs/test3/lib/python3.7/site-packages/pytest_django/fixtures.py:298: TypeError

I investigated and it's because authtools defines create_superuser like this:

    def create_superuser(self, **kwargs):

using only one positional argument (self). The pytest-django fixture tries to invoke the function like Django expects up until 3.0, using username, email and password. In 3.0 only username is required so this problem might be solved but I'm on 2.2 and you seem to support 1.11 and maybe earlier too.

So is this a bug? I can work around it for now but thought I'd notify you. And thanks for a great package btw ☺️ .

Error occurring in django 1.7

For some reason pkg_resources can not find the version of the lib authtools and generates the error below:

 mod_wsgi (pid=12640): Target WSGI script '...\\wsgi.py' cannot be loaded as Python module.
 mod_wsgi (pid=12640): Exception occurred processing WSGI script '...\\wsgi.py'.
 Traceback (most recent call last):
   File "...\\wsgi.py", line 48, in <module>
     _application = get_wsgi_application()
   File "...\\django\\core\\wsgi.py", line 14, in get_wsgi_application
     django.setup()
   File "...\\django\\__init__.py", line 21, in setup
     apps.populate(settings.INSTALLED_APPS)
   File "...\\django\\apps\\registry.py", line 115, in populate
     app_config.ready()
   File "...\\xadmin\\apps.py", line 13, in ready
     self.module.autodiscover()
   File "...\\xadmin\\__init__.py", line 55, in autodiscover
     import_module('%s.adminx' % app)
   File "...\django\\utils\\importlib.py", line 46, in import_module
     __import__(name)
   File "...\\app\\adminx.py", line 4, in <module>
     from authtools.forms import UserCreationForm, AdminUserChangeForm
   File "...\\pyenv\\Lib\\site-packages\\authtools\\__init__.py", line 3, in <module>
     __version__ = pkg_resources.get_distribution('django-authtools').version
   File "...\\pkg_resources\\__init__.py", line 539, in get_distribution
     dist = get_provider(dist)
   File "...\\pkg_resources\\__init__.py", line 419, in get_provider
   File "...\\pkg_resources\\__init__.py", line 940, in require
     needed = self.resolve(parse_requirements(requirements))
   File "...\\pkg_resources\\__init__.py", line 827, in resolve
     raise DistributionNotFound(req, requirers)
 DistributionNotFound: The 'django-authtools' distribution was not found and is required by the application

If the comment line below the error disappears (authtools.init):

pkg_resources.get_distribution('django-authtools').version

See my environment is to:

Python 2.7.9
Django 1.7
Xadmin (branch django 1.7)
Apache2 (with wsgi)

django-authtools - It is installed in a virtual environment (created with virtualenv).

AbstractEmailUser does not normalize emails

I noticed that AbstractEmailUser does not reproduce the .clean() method that Django's AbstractUser provides, which means normalize_email() (lowercasify the domain portion) is not being invoked on save.

https://github.com/django/django/blob/master/django/contrib/auth/models.py#L363-L365:

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

I would assume that this is deliberate, but authtools' implementation of UserManager.create_user() does include normalize_email()

https://github.com/fusionbox/django-authtools/blob/master/authtools/models.py#L12-L17

    def create_user(self, email, password=None, **kwargs):
        email = self.normalize_email(email)
        // ...

Which means that users created with manage.py createsuperuserwill have their emails normalized, but users created through the Django Admin will not.

Use a namespace?

I'm running into an issue where {% url 'password_reset' %} is returning the wrong url because another app in my project has registered an url with that name. And I can't just move that other app (mezzanine) up before authtools in urls.py because Mezzanine includes a catch all url so it should come last.

So wouldn't it be a good idea in all cases to use a namespace so one could use authtools:password_reset instead?

Question: Accepting contributors?

Hey folks,

Just wondering what your contributors landscape looks like. I'm going to be using this library in a production environment and want to give back - let me know what can help.

Thanks

help_text for password form incorrect url

When I click on this form in the route /admin/authtools/user/<id>/ the link redirects to /admin/authtools/user/password/ instead of /admin/authtools/user/<id>/password.

Handling of SMTPRecipientsRefused exception

Following the docs on "How To Create Users Without Setting Their Password" https://django-authtools.readthedocs.io/en/latest/how-to/invitation-email.html (relevant code snippet below), the call to reset_form.save could trigger SMTPRecipientsRefused if the recipient email address is invalid, currently it will result in a 500 as-is. My understanding is that usually form error validations are handled in the clean_* method, any suggestions on how to deal with the SMTPRecipientsRefused exception in this case?

    def save_model(self, request, obj, form, change):
        if not change and (not form.cleaned_data['password1'] or not obj.has_usable_password()):
            # Django's PasswordResetForm won't let us reset an unusable
            # password. We set it above super() so we don't have to save twice.
            obj.set_password(get_random_string())
            reset_password = True
        else:
            reset_password = False

        super(UserAdmin, self).save_model(request, obj, form, change)

        if reset_password:
            reset_form = PasswordResetForm({'email': obj.email})
            assert reset_form.is_valid()
            reset_form.save(
                request=request,
                use_https=request.is_secure(),
                subject_template_name='registration/account_creation_subject.txt',
                email_template_name='registration/account_creation_email.html',
            )

PasswordChangeForm and EmailChangeForm (and their views)

I just wrote my own PasswordChangeForm/PasswordChangeView in one of my project. (The form is two password fields, and ask for the current password). I also created EmailChangeForm/EmailChangeView (with newemail/password confirmation)

IMHO, it sounds like something that should go in authtools. What do you think?

FYI, It looks like this:

class UpdatePasswordForm(forms.Form):
    password1 = forms.CharField(label='New password',
                                widget=forms.PasswordInput)
    password2 = forms.CharField(
        label='Password confirmation',
        help_text='Same password as above.',
        widget=forms.PasswordInput,
    )
    current = forms.CharField(label='Current password',
                              widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        self.instance = kwargs.pop('instance', None)
        assert self.instance is not None
        super(UpdatePasswordForm, self).__init__(*args, **kwargs)

    def clean_current(self):
        password = self.cleaned_data['current']

        assert self.instance is not None
        if not self.instance.check_password(password):
            raise forms.ValidationError("The current password was invalid.")

        return password

    def clean(self):
        cleaned_data = super(UpdatePasswordForm, self).clean()
        if cleaned_data['password1'] != cleaned_data['password2']:
            raise forms.ValidationError("Passwords didn't match")
        return cleaned_data

    def save(self, commit=True):
        assert self.instance is not None
        self.instance.set_password(self.cleaned_data['password1'])
        if commit:
            self.instance.save()
        return self.instance

class UpdatePasswordView(EnsureAuthMixin, UpdateView):
    form_class = UpdatePasswordForm
    template_name = 'auth/update_password.html'

    def get_object(self):
        user = self.request.user
        assert not user.is_anonymous()
        return user

I think pip installation doesn't install lastversion.

I think there are different version source between git and pip.
I tried to install as next (in windwos)
$ pip install django-authtools
but it has different part within forms.py, views.py (AuthenticationForm)
Please, just check, if it is wrong.

Missing migration in Django 1.8

I'm getting a missing migration warning on 1.8 with authtools:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('authtools', '0002_django18'),
    ]

    operations = [
        migrations.AlterField(
            model_name='user',
            name='groups',
            field=models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups'),
        ),
    ]

Permission escalation issue?

There is a potential permission escalation issue with the out-of-the-box configuration of authtools.

Users who are is_staff and have permissions to see the User section can currently edit their own permissions and also edit the passwords of superusers.

I did some work in one of my projects to prevent this, but I don't think it's possible to make this generic.

    def get_fieldsets(self, request, obj=None):
        if not obj or request.user.is_superuser:
            return super(UserAdmin, self).get_fieldsets(request, obj)

        # permission escalation avoidance.  Staff can change each others'
        # passwords, but not edit permissions or change superusers' passwords.
        base_fields = copy.deepcopy(BASE_FIELDS)
        if obj and obj.is_superuser:
            base_fields[1]['fields'] = REQUIRED_FIELDS
        return (base_fields,) + self.declared_fieldsets[2:]

There is still the possibility that an is_staff User gains more permissions by changing the password of other is_staffers, but they still won't be able to gain superuser access.

All this being said, I think the best we can do is just to put some warnings in the docs. Thoughts?

Change password link broken

When trying to use the link in the django user admin to change a user's password, I get a 404.

Clicking the link on the page: "Raw passwords are not stored, so there is no way to see this user's password, but you can change the password using this form", should link to /admin/accounts/user/{pk}/password/, but it is instead linking to /admin/accounts/user/password/

BetterReadOnlyPasswordHashWidget is broken for view only users

Django 2.1 added view only permission. This break BetterReadOnlyPasswordHashWidget:

TypeError: 'NoneType' object is not a mapping

...

  File "django/contrib/admin/helpers.py", line 210, in contents
    return widget.render(field, value)
  File "authtools/forms.py", line 35, in render
    final_attrs = flatatt(self.build_attrs(attrs))
  File "django/forms/widgets.py", line 239, in build_attrs
    return {**base_attrs, **(extra_attrs or {})}

image

I think changing render's attrs=None default value, or add or {} to build_attrs would probably fix this.

email uniqueness is done with case-sensitivity on some databases

Postgres performs string comparison case-sensitively, mysql does it case-insensitive. This means that on postgres, [email protected], [email protected] and [email protected] are all distinct emails, and a user could register with each one.

Domain names are not case sensitive, so at least the domain part should lowercased. The local part of an email address is technically case sensitive, but I don't think it is in practice.

The easiest way to accomplish this would be to lowercase email addresses before storing them, but it might be wrong to mangle addresses like that.

Authtools' user model doesn't work with utf8mb4 on MariaDB/MySQL

See this comment in the Django 1.10 release notes re: "AbstractUser.username max_length increased to 150":

We considered an increase to 254 characters to more easily allow the use of email addresses (which are limited to 254 characters) as usernames but rejected it due to a MySQL limitation. When using the utf8mb4 encoding (recommended for proper Unicode support), MySQL can only create unique indexes with 191 characters by default.

Authtools' 255 character email field walks into exactly that problem.

I doubt you'll want to change max_length just to satisfy MySQL, so two thoughts.

First, you could make max_length configurable via settings, with a default of 255?

Second, you could document the problem and the workaround? The workaround is straightforward:

class User(authtools.models.AbstractNamedUser):
    email = django.db.models.EmailField(
            _('email address'), max_length=190, unique=True)

Of course, you also have to point AUTH_USER_MODEL to that class, and register the class in the admin using something like:

admin.site.register(User, authtools.admin.NamedUserAdmin)

Authtool not recognized in AWS deployment

It seems the authtools module is not recognized when deploying the application in AWS EC2 (unless I am doing something wrong which is quite likely). I have posted the issue on SO (https://stackoverflow.com/questions/44902540/cannot-overwrite-django-authentication-templates-in-aws), I would appreciate a sanity check from someone to understand if there is an issue with the module itself and it's compatibility with the Django/Python version deployed by AWS or if I am missing something.
Thanks

Django 1.8 ProgrammingError: relation "auth_group" does not exist

I've created a new db for my Django 1.8 app. doing ./manage migrate throws this error:

...
Synchronizing apps without migrations:
  Creating tables...
    Creating table authtools_user
    Running deferred SQL...
Traceback (most recent call last):
  File "./manage.py", line 12, in <module>
    execute_from_command_line(sys.argv)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 330, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/base.py", line 390, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/base.py", line 441, in execute
    output = self.handle(*args, **options)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 179, in handle
    created_models = self.sync_apps(connection, executor.loader.unmigrated_apps)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 317, in sync_apps
    cursor.execute(statement)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/db/utils.py", line 97, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/user/.venvs/py2.7/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 62, in execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "auth_group" does not exist

however, installing Django 1.7, migrating the app and then upgrading Django to 1.8 works fine.

Run test suite against Django 1.8

This was going to be a PR, until I discovered that most of django.contrib.auth.tests (which the authtools suite imports) was moved out of the django namespace in Django 1.8.x. I presume this is why Django 1.8 isn't already included in Tox/Travis.

Possible options:

  • Add a vendor/django_1_8/tests/auth_tests directory (possibly as a git submodule) and import from there when testing Django 1.8
  • Collaborate with e.g. https://github.com/arteria/django-compat to make a Distribution of Django's test suite.
  • Rewrite the tests so they don't use those parts of the Django test suite

Thoughts?

[Duplicate for #63] Migration missing

Creates migration in site-packages dependant on 0002_django18 when executing makemigrations

# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2015-12-05 18:13
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('authtools', '0002_django18'),
    ]

    operations = [
        migrations.AlterField(
            model_name='user',
            name='groups',
            field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
        ),
    ]

Use with django-axes not supported

I have found that the AuthenticationForm does not have the request prop available to send through to authentication back-ends here https://github.com/django/django/blob/06909fe084f87a65459a83bd69d7cdbe4fce9a7c/django/contrib/auth/forms.py#L205 where it calls authenticate(self.request the value of self.request will always be None

This means that I am unable to make use of django-axes authentication back-end that requires this value to be set.

Below I have tried my best to track the flow of logic:

  1. LoginView uses AuthenticationForm https://github.com/fusionbox/django-authtools/blob/master/authtools/views.py#L153
  2. When submitting a form dispatch is called
    return super(LoginView, self).dispatch(*args, **kwargs)
  3. Calls the dispatch method here https://github.com/django/django/blob/06909fe084f87a65459a83bd69d7cdbe4fce9a7c/django/views/generic/base.py#L89
  4. Since we are posting (loggin in) it in turn calls this method from ProcessFormView https://github.com/django/django/blob/06909fe084f87a65459a83bd69d7cdbe4fce9a7c/django/views/generic/edit.py#L142
  5. The form.is_valid() is called from the form fetched here https://github.com/django/django/blob/06909fe084f87a65459a83bd69d7cdbe4fce9a7c/django/views/generic/edit.py#L33 which DOESN'T pass through the request prop
  6. AuthenticationForm's clean method calls authenticate https://github.com/django/django/blob/06909fe084f87a65459a83bd69d7cdbe4fce9a7c/django/contrib/auth/forms.py#L205

At this point it flows through the authentication back-ends and django-axes throws an error due to request being None. Please help me to fix, or find a workaround.

Thank you

[Minor issue] Warning: `request.REQUEST` is deprecated

Hi there!

The CBV WithNextUrlMixin currently generates the following warnings:

RemovedInDjango19Warning: `request.REQUEST` is deprecated, use `request.GET` or `request.POST` instead.
  if self.redirect_field_name in self.request.REQUEST:

RemovedInDjango19Warning: `request.REQUEST` is deprecated, use `request.GET` or `request.POST` instead.
  redirect_to = self.request.REQUEST[self.redirect_field_name]

It's not a major concern at the moment, but I thought I'd contribute this re-write:

def get_next_url(self):
        # if self.redirect_field_name in self.request.REQUEST:
        #     redirect_to = self.request.REQUEST[self.redirect_field_name]
        #     if is_safe_url(redirect_to, host=self.request.get_host()):
        #         return redirect_to
        redirect_to = self.request.POST.get(self.redirect_field_name,
                                            self.request.GET.get(self.redirect_field_name, ''))
        if is_safe_url(redirect_to, host=self.request.get_host()):
            return redirect_to

I'm leaving the old code commented above, so that you can easily compare the change.

Thanks for all the hard work. ;-)

Change password link broken again

There seems to have been a regression with issue #62 and #64 using Django==1.10.3 and django-authtools==1.5.0

As a workaround i did this custom form (without the translation _):

from django.contrib.auth.forms import UserChangeForm as DjangoUserChangeForm


from authtools.forms import UserChangeForm


class CustomAdminUserChangeForm(UserChangeForm):
    def __init__(self, *args, **kwargs):
        super(CustomAdminUserChangeForm, self).__init__(*args, **kwargs)
        if not self.fields['password'].help_text:
            self.fields['password'].help_text = (
                "Raw passwords are not stored, so there is no way to see this"
                " user's password, but you can change the password using"
                " <a href=\"../password/\">this form</a>.")

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.