Code Monkey home page Code Monkey logo

lastuser's Introduction

Lastuser

Lastuser has been merged into Funnel is no longer maintained a standalone app. This repository is archived. Historical notes follow:


Build status Coverage status

User management is a pain. Apps shouldn't have their own user management code if it can be centrally managed. Lastuser does it for HasGeek. This open source code release is intended to help you examine our code, work with our APIs, and lend a helping hand where needed.

Usage

Lastuser requires PostgreSQL and Python 2.7. A virtualenv is strongly recommended. Instructions:

$ git clone https://github.com/hasgeek/lastuser
$ cd lastuser
$ pip install -r requirements.txt
$ createdb lastuser
$ cp instance/settings-sample.py instance/development.py

Edit to customize instance/development.py as needed, then populate the database:

$ python manage.py createdb

You should now be able to run the development server, accessible at http://localhost:7000:

$ python runserver.py

To use Lastuser effectively, you will need to create an /etc/hosts entry pointing to localhost, for Lastuser and any client apps you may need:

127.0.0.1 lastuser.mymachine.local
127.0.0.1 clientapp.mymachine.local

Tests

Before you run the tests:

$ pip install -r test_requirements.txt
$ cp secrets.test.sample secrets.test

secrets.test contains API keys for various external services Lastuser works with. Note that Lastuser's functional tests are incomplete at this time.

Next, create a test database. Do not use your development database for this as the test database is wiped after each run of the test suite:

$ createdb lastuser_test_app

Run the tests from the root directory of the project:

$ ./runtests.sh

Support

Feel free to file a bug report for anything that doesn't work or is amiss in our code. We're available for a chat in #tech on friends.hasgeek.com.

lastuser's People

Contributors

btbytes avatar harisibrahimkv avatar iambibhas avatar jace avatar karthikb351 avatar kracekumar avatar miteshashar avatar netroy avatar nigelbabu avatar punchagan avatar pyup-bot avatar qurbat avatar salmanulfarzy avatar shreyas-satish avatar tuxdna avatar vidya-ram 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

lastuser's Issues

Check usernames against userids

When a username is blank in Lastuser, client apps that have Profiles use the userid instead. This will fail for User A if User B's username is the same as User A's userid.

When a user picks a username, it should be checked for uniqueness against all userids.

Underscorify all Model properties

By convention, we want underscores between words in all the Model properties and functions.
Each change will require major renames in various files across models, views, templates & forms. Each change should hence be pushed with considerable amount of diligence.

Password strength

Currently user can register an account with password length 1, We need to have password strength validator.

Reorganize lastuser server into blueprints

The current lastuser architecture provides very little control to implementations. The code should be reorganized into blueprints, with implementations having the option to deploy only the parts that are needed:

  1. lastuser_core provides the database models, the internal resource registry and the core functions
  2. lastuser_oauth provides the /login, /logout, /auth, /token and /api endpoints
  3. lastuser_ui provides the UI for managing the user profile, organizations and permissions.

An implementation may choose to provide #1 and #2 but not #3, folding that functionality into a client app. This helps prevent duplicated functionality for users.

Custom login messages

When a user is logging into an app, the app should be able to set a custom login message with instructions. For instance, the job board should specifically instruct that the login is for the individual, not the company.

External ids for organizations

External ids should be linkable to organizations instead of users. This is similar to login providers, but cannot be used for login and links to GitHub organizations, Facebook pages, etc. Twitter ids behave the same as with a login provider, while Google is not available (except G+ pages).

Rename "organizations" to "groups"

The term "organization" confuses people into assuming that it's only meant for formal organizations. Renaming the concept to "group" will make this easier to accept.

robots.txt required

Googlebot is attempting to login by hitting the /auth page. Since Googlebot isn't a user and can't login, this is pointless.

/auth and /token should be denied to bots in robots.txt.

Organizations should take a parent organization

In the common scenario where an 'organization' is an event series, owned by another organization that is the company that runs the events, there should be a way to link these two and allow teams to be inherited from one, to simplify team management.

Organizations need a parent_id, where the parent cannot itself have a parent, and organizations.teams (or a new all_teams) should include the parent's teams.

User.organizations and User.organizations_owned should include child organizations.

Check for cookies

If the user has disabled cookies in their browser, login will fail without explaining to the user why. Users need to be notified if they have cookies disabled.

Twitter OAuth needs error handling decorator

The Twitter OAuth decorator in oauthclient.py raises an OAuthException if Twitter denies the login attempt. Unfortunately, this propagates as a 500 error and is shown to the user as an app error.

Since exceptions in decorators cannot be trapped in the decorated function, we need another decorator on top of the Twitter decorator, whose sole purpose is to watch for OAuthException and render a friendly error message suggesting users try again. It could simply flash a message and redirect back to the login page (restoring the next component of the request from the session).

Validate Google login data

Google's OpenID login process sends user data via a browser GET request. Is this request signed? Is the data tamper proof? If not, the email address provided can no longer be trusted.

Tokenized names for users

User.fullname currently stores the user's full name as reported by them (or sometimes automatically guessed from a login provider). There are contexts where we'll want a first name instead of a fullname, so we should store first/middle/last names separately.

However, trying to guess first/middle/lastname automatically or constructing a fullname out of them is a minefield given varying cultural contexts (and native scripts when the name is originally non-Latin).

Lastuser needs to model the name fields to (a) work with as little information as possible, (b) be able to extract the name components when available and (c) provide a user interface that allows editing each component without overburdening the user.

(This issue is not a short term priority as having only fullname is acceptable for the vast majority of use cases).

"Members" team

Like "Owners", organizations should have a "Members" team that is the default team for anyone who is a member of the organization. All owners should be members by default.

The members team does not provide administrative access. It's instead the default team for anywhere that access has to be restricted in any way (filing expense reports in Kharcha or posting to a discussion group). The Members team is used in situations where managing teams is too much detail.

An app that does not have access to an organization's teams can still be aware of the existence of Owners and Members (and a user's membership in these) and can therefore be reasonably functional until team access is granted.

Transient user tracking

Many site users do not login until after much convincing. The activities they performed on the site pre-login are however valuable and could be linked to their logged-in profile (for example, jobs viewed on Hasjob or videos on HGTV).

Problem: right now, there is no way to track such transient users because they have no user accounts.

Idea: Add a flag to the User model to include a transient flag. For every cookie-enabled non-logged-in visitor, create a transient user account when they perform their first significant action (including actions like adding items to a shopping cart), and keep adding to this User object. When they finally login, if they have an existing User object, use Lastuser's merge user support to merge data. If they don't, make the User object a permanent user.

As a periodic sweep, remove transient accounts and data where the user has not visited again in a month or so.

Undecided: should this be centralized in Lastuser or decentralized in Flask-Lastuser? If the same user shows up on multiple sites, sharing a transient id is tricky for security rasons. The user has not yet agreed to share data with the specific site. A decentralized server can go about its business without such complications.

A decentralized approach, however, will mean that the user's record is even more fragmented and there is a chance of data loss when they actually login, because another site that previously saw the same visitor is not yet aware that they have a proper user account. Centralization will make sync more efficient.

Client app URIs must be validated

When creating a client app, the domain in the URIs for Redirect, Notification and Resource MUST match that in the website. This is required since only the Website URI is shown to users when confirming their assent.

Old userid tracking

Lastuser needs a table for old userids, from ids discarded when accounts are merged. When a user logs into a client app, these old ids are supplied as part of the userinfo and the client can perform data merger.

The same mechanism can be used later for push notifications.

Sub-organizations

This is not a fully thought-out proposal. It may not be feasible.

Sub-organizations are like organizations, but bound to a parent. They have a name that is unique within the scope of the parent and they can contain their own teams.

Sub-organizations are used for event editions. For example, the metarefresh organization has 2012 and 2013 sub-organizations, each of which can have distinct teams to indicate the Program Committee, Participant Directory, etc.

Post-profiles project, they'll get URLs like these:

Inter-app messaging

Lastuser needs to provide a mechanism for client apps to leave messages for each other. This can be used, for example, for BoxOffice to post an invoice in Billgate (using Billgate's API), and for Billgate to notify BoxOffice of successful payment (via the messaging API).

The messaging API helps communicate across firewalls, since Lastuser is always accessible, and ensures message delivery even if an app is down (though Lastuser is now the single point of failure).

Preserve old UserEmail

When a user removes an email address (which was verified), preserve it in a new UserPastEmail (or similar) model, with no unique constraint on the email address.

Past emails can be a useful indicator of past associations.

Public and private teams

Teams are currently all private -- their existence is only revealed to users and organization owners.

There should be a public flag on teams instead, default False, allowing for some teams to be made public.

For apps, the "Requires access to teams" flag will now be about access to private teams as public teams are shared by default.

Use Flask-SQLAlchemy "binds"

Binds allow a blueprint to be embedded in another app while maintaining an independent database connection. Lastuser should use binds to allow the UI to be embedded in Hasweb.

Wildcard scope required

For apps that provide a comprehensive function, such as hasweb, which manages everything related to user profiles, asking for permission to every single resource in lastuser makes for an unnecessarily long scope string. Apps (trusted-only?) should be able to ask for wildcard permissions such as email/* or even just *.

Rename Client.owner to ownername/ownertitle

The Client.owner property's name is misleading. It sounds like it should return an object, but instead returns a string. ownername sounds better, but name has a specific meaning in our models (it refers to URL names). ownertitle is semantically correct since title is the user-facing value, but it sounds odd.

The column should be renamed to one of ownername or ownertitle (but which?).

Password reset flag needed

User accounts need a flag that requires them to change password on the next login.

The requires_login decorator should recognise this flag and prevent any other user activity, especially access to /auth.

Two-factor authentication

Lastuser needs two-factor authentication for anyone using their account to manage important data. Implementing it requires:

  1. Support for verifying mobile numbers and sending text messages to mobile numbers anywhere in the world, or making phone calls to read out codes (Twilio SMSes don't reach Indian numbers that are in the DND registry).
  2. Support for Google Authenticator as a mobile app.
  3. A mechanism by which to reset account access if the user has lost their credentials (phone/email).

Login beacon

Sites are often out of sync with Lastuser w.r.t the user's logged in state. The user may be logged into the site but not the app or vice versa.

The login beacon is a JS script loaded from the Lastuser server in all app sites that attempts to fix this:

  1. If the user is logged into Lastuser but not the app site, and the app is a trusted site OR the user has an existing access token to this site, it logs the user in automatically and prompts for the page to be reloaded. (Question: how does it login without user interaction? If an iframe, there's cross-site scripting concerns.)
  2. If the user is logged into the app but not Lastuser, it logs the user out immediately.

Questions:

  1. Should this script be reloaded for every page, using its own request as indicator of user state?
  2. Should the script be cached, and instead hit a beacon API endpoint that returns a lightweight result?
  3. What are the implications to server load on Lastuser if every page on every app loads it?

Password expiry

Some client apps may need login sessions to be shorter than browser sessions for security reasons. LastUser should:

  1. Record the datetime when a user authenticated
  2. In an app's config, add an option for session duration

When a user logs into an app with a custom session duration and the user is already logged into LastUser, LastUser should:

  1. Verify that the login datetime is more recent than the app's session time and, if not,
  2. If the user logged in with a password, ask them to re-enter the password (alone), or logout and login again, or
  3. (this is iffy) If with an external service, indicate which one and ask them to authenticate again

Point 3 is iffy. OAuth services will return without showing any UI since there is an existing token for the current user and the lastuser app. Perhaps security-sensitive apps should insist on the user having a lastuser password before they are allowed to login.

Deleted user flag

Lastuser needs a deleted flag or some kind of a status flag on the User model to indicate a deleted/suspended user account. This flag should be queried everywhere that the User model is queried.

Email should be lowercase

Emails are not case-sensitive. They should always be lowercase. Forms that ask for an email address should ensure they are converted into lowercase before saving.

Email domain for organizations

Organizations can have an optional but unique email domain. If specified, any user who has an email address with the same domain is automatically added to the Members group (see #28).

The user who is configuring the organization can only claim email domains that they have a currently valid email address at.

Known webmail domains can be blacklisted from the app's configuration.

Login resource

The login resource should require a user to be logged in with a specific login provider. login/linkedin, for instance, mandates LinkedIn login.

The /auth endpoint will refuse to let the user proceed unless they have the specified login service applied to their account.

To reduce the chances of a duplicate account, the login screen encourages users to login with the last used service and then asks for the required service to be added to the user's account.

Client-owned teams

Teams need a nullable client_id column that indicates if the team was created by a client app. Client apps can use this to directly add users to a team, bypassing the Lastuser UI.

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.