The result of db.User.get_dict never contains the keys 'api_keys' or 'permissions'. The keys returned by get_dict are 1) all the User table columns, 2) the keys explicitly defined in User.__json__, and 3) the keys defined in User.get_api_data, none of which include the two blacklisted keys.
'api_keys' would be returned if __json__ called get_api_data with argument details=True; but currently that is not the case.
In case there's a reason why these two keys must never appear in an AuthUser object, the check has not been removed entirely; instead, it's been turned into an assertion. This way, it will be noticed if __json__ is later modified to request detailed API data, for instance.
Because the method is only used by AuthUser, and also because it's an awful thing to do (copying a large but ill-defined set of attributes from one object to another), and we don't want usage to spread.
auth: construct AuthUser from either user_id or db.User object
If the caller already has the database User object, there's no reason for AuthUser to look it up again.
The `api_key` lookup functionality is dropped, because 1) it's only used in one place, and 2) it's simple enough for the caller to do the lookup itself.
The `user_id` lookup functionality is kept, because 1) it's frequently used, and 2) far from a simple `User.get(id)` lookup, it has a complex interaction with UserModel. (That cleanup will have to wait for another day.)
All calls of the form `AuthUser(user_id=x.user_id)` can be replaced with `AuthUser(dbuser=x)`, assuming `x` is a db.User. However, verifying that assumption requires a manual audit of every call site, since `x` might also be another `AuthUser` object, for instance. Therefore, only the most obvious call sites have been fixed here.
auth: refactor user lookup in AuthUser constructor for clarity
First, note that `fill_data` checks that the specified `db.User` is `active` before copying anything, and returns False if not.
Now, previously when calling e.g. `AuthUser(user_id=anonymous_user_id)`, `_propagate_data` would explicitly refuse to look up the anonymous user, but then fall back to the anonymous user anyway (if `active`), or use None values (if not `active`).
Given the same situation, the new code simply looks up the anonymous user like it would any other user, and copies data using `fill_data`. If the anonymous user is not `active`, we fall back to the existing code path and behave as before (that is, use None values).
auth: remove username from AuthUser session cookie
There's no reason to store the username when we store the user ID. We have load the user from database anyway under all circumstances, to verify e.g. that the user is (still) active.
This does not impact application code, but does impact a number of test cases which explicitly checks the username stored in the session.
AuthUser looks up the user based on the first of `user_id`, `api_key` and `username` that is not None *and* does not refer to the default (anonymous) user. In practice, the arguments always refer to the same user, so there's no point in specifying more than one of them.
auth: have fill_data take User object, not lookup key
Simplify the UserModel.fill_data interface by passing the actual db.User object instead of a key by which it can be looked up. This also saves a lookup in case the db.User is already loaded (which for now is only the case in one place, but that'll change in the following changesets).
UserModel: remove methods that are redundant with db.User
UserModel().get_by_api_key is exactly equivalent to User.get_by_api_key.
UserModel's get_by_username and get_by_email are not exactly identical to their db.User counterparts, due to a difference in the order of optional arguments. Fortunately, these optional arguments are never used.
admin: e-mail: don't repeat the e-mail settings from the .ini file
None of the settings from the .ini file are currently listed in the admin interface, except for e-mail. There is no need for such an exception: either we list all settings or none.
The repo "show" controller didn't do anything and was unused. There was a routing GET entry for it but it was only used for generating URLs for DELETE and PUT operations that have separate controllers that happen to have the same URL.
Use the right routing entries when generating URLs and drop the dead code.
cleanup: check for None object identity in cases where that is what the 'contract' says
Avoid applying bool() on complex objects - it might return something unexpected such as the key (which might be 0 and thus be false). Checking for None is more safe and faster.
e-mail: remove unused setting error_message from ini files
The ini files and templates contain a commented setting of 'error_message' which does not seem to be used. It is referring to the error_message variable in Paste, which has as description (Paste:ErrorMiddleware):
When debug mode is off, the error message to show to users.
However, setting this value apparently made no effect at all in Kallithea.
Note: groups_choices from the db module is only used from this function and should perhaps also be extracted ... but it is also closely related to other stuff that is (mis)placed in the db module so perhaps not ...
repos: refactor repo group handling - extract generic functionality that can be used consistently
By using the right repo group list in the form, it is no longer possible for users to pick wrong repo creation locations ... and doing so anyway will be caught earlier on with a more generic error message at the specific place.
The UI was a bit weird ... probably in an attempt of making it editable while hiding passwords. Instead, just show the URL with password hidden, and only save it back if it changed.
The UI only contains the clone_uri with passwords hidden. It will thus only be saved when the form result is different from the value that was shown to the user.
h.tooltip did more magic in the past - now it just did a douple (or triple?) escape of html.
c9cfaeb1cdfe removed most of the need for double escaping - and the places where it is used, it must be 'tagged' with the safe-html-title class. Thus, none of the remaining uses of h.tooltip are relevant (and might even be wrong); normal automatic template escaping is just fine.
This is mostly: sed -i 's,title="\${h.tooltip(\([^}]*\))}",title="${\1}",g' `hg mani`
data_table: use simple 'escape' function instead of 'tooltip' function
The values will end up being double escaped when h.escape is used in template expansion and turned into a string which then will be escaped in the template.
changeset: make code more stable against unexpected comments
Avoid passing None to the template in comments. This makes the code more correct and fixes a crash seen while hacking, probably never seen in the wild.
BaseController: hide "Log out" link for external login sessions
If user is authorized by external means (API key or container auth), Kallithea is not actually able to log the user out and should not show the "Log out" link.
* All serialization/deserialization logic is now in one place.
* CookieStoreWrapper is gone; any login sessions established in 2012 or earlier will be terminated and users will have to log in again.
* The term "cookie store" has been dropped in favor of simply "cookie" (the value is not a cookie "store" or data repository, but just the actual cookie/session serialization of AuthUser).
BaseController: enable container authentication on all pages
Previously, user had to visit the login page to log in using container authentication; this now happens on every page load, unless user has an existing login session.
The container authentication result is cached in session on success.
Instead of having one controller method ('auth_settings', which handles POST) call another controller method ('index', which handles GET), have both methods call a third, common '__render' method.
This makes it clear which arguments 'index' really takes (none). It's also seen that the 'prefix_error' argument is always False, so it can be removed. Finally, '__load_defaults' is no longer called twice when POSTing invalid form values.
Since the formglobals variable is used only to populate the template context, just assign values directly to `c` instead. This does involve dropping the (very large) debug log entry listing all the formglobals.
AuthSettingsController: rename dictionary key for consistency
Rename 'auth_plugins_shortnames' to 'plugin_shortnames' for consistency with 'plugin_settings', and to emphasize that it's not one of the values retrieved from the database using get_auth_settings (all of which start with 'auth_').
In formglobals, the provided 'auth_plugins' default value is always replaced with the real database value, returned along with other plugin settings by Setting.get_auth_settings.
We can safely assume that the database value exists, since not only does db_manage initialize the 'auth_plugins' option upon database creation, but other authentication modules already assume its existence.
For instance, Settings.get_auth_plugins() is equivalent to
Settings.get_auth_settings()['auth_plugins']
except that get_auth_plugins will throw AttributeError, not KeyError, if the 'auth_plugins' key does not exist in the database.
log_in_user: extract user session setup from LoginController
The next changeset will need to set up a user login session outside LoginController. 'log_in_user' extracted and added as a top-level function in kallithea.lib.base since the code doesn't need access to the current controller.
Code refactored to take a User object instead of a username, to allow callers flexibility in how the user should be looked up.
Untangle session cookie authentication. If no session cookie is set, AuthUser constructor will be called with user_id set to None (the argument default value), and will never raise a UserCreationError. Thus that case can safely be moved to the end of _determine_auth_user and outside the try-except block.
If a session cookie *is* set, but we get a UserCreationError, we fall through to the "no cookie" case, which is also effectively the same behavior as before. (Not sure what circumstances, if any, can actually trigger a UserCreationError here, since the user is already logged in and - presumably - created, plus the user is identified by the Kallithea database ID, not user name, which would make it difficult to create a new user... but judging from the existing code, it's possible.)
Untangle API key authentication. Creating an AuthUser from an API key can leave the AuthUser authenticated or not, depending on key validity and Kallithea configuration; but either way, _determine_auth_user will not change this fact, and we can return early.
AuthUser: simplify check_ip_allowed and drop is_ip_allowed
check_ip_allowed is always called with user_id and inherit_from_default arguments taken from the same User/AuthUser object, so just take that object instead. This simplifies the is_ip_allowed method to the point where it can be removed.
pullrequest: re-add username when adding reviewers
Commit 90e982b6bca8 removed the username when adding reviewers, to align the way new and existing reviewers are displayed. However, when a user does not have a name set, the list of reviewers becomes useless unless the username is displayed too.
Some miscellaneous changes that didn't really fit in the previous patches: - clarification of variable names - removal of unnecessary underscore in MembersAutoComplete - avoid hardcoded div specifications
The owner field of a repository setting was supposed to be autocompletable, but never really did (at least not in Kallithea, probably it once did in Rhodecode).
Instead of making yet another 'OwnerAutoComplete', make a generic SimpleUserAutoComplete that can be reused in other places that only need completion of a text input field.
autocomplete: introduce function to set up basic autocomplete functionality
To set up an autocomplete instance, there is quite some boilerplate that is with minimal differences between instances. Move this to a helper function to reduce duplication, while still allowing each specific case to tweak behavior.
autocomplete: remove redundant specification of responseSchema
YAHOO.util.DataSource.responseSchema determines which fields from the data source are returned upon requests. In the case of user/group autocompletion, the data source is a static JavaScript array containing only the relevant fields. When not specifying a responseSchema, all fields of the selected entry are returned, which is fine (in fact, the responseSchema currently specified just mentions all fields, redundantly).
autocomplete: clean up handlers for itemSelectEvent
The handlers that execute when an autocompleted item is selected are really specific and cannot be factored out. Nevertheless, some cleanup:
- rationalize indentation - remove redundant copy/pasted comments - remove redundant group handling in MentionsAutoComplete - remove redundant checks on 'oData.nname != undefined', used to differentiate user vs. group completion, in places that only allow user autocompletion