Files
@ f734d107296e
Branch filter:
Location: kallithea/docs/theme/nature/static/nature.css_t - annotation
f734d107296e
3.8 KiB
text/plain
auth: for default permissions, use existing explicit query result values instead of following dot references in ORM result objects
There has been reports of spurious crashes on resolving references like
.repository from Permissions:
File ".../kallithea/lib/auth.py", line 678, in __wrapper
if self.check_permissions(user):
File ".../kallithea/lib/auth.py", line 718, in check_permissions
return user.has_repository_permission_level(repo_name, self.required_perm)
File ".../kallithea/lib/auth.py", line 450, in has_repository_permission_level
actual_perm = self.permissions['repositories'].get(repo_name)
File ".../kallithea/lib/vcs/utils/lazy.py", line 41, in __get__
value = self._func(obj)
File ".../kallithea/lib/auth.py", line 442, in permissions
return self.__get_perms(user=self, cache=False)
File ".../kallithea/lib/auth.py", line 498, in __get_perms
return compute(user_id, user_is_admin)
File ".../kallithea/lib/auth.py", line 190, in _cached_perms_data
r_k = perm.UserRepoToPerm.repository.repo_name
File ".../sqlalchemy/orm/attributes.py", line 285, in __get__
return self.impl.get(instance_state(instance), dict_)
File ".../sqlalchemy/orm/attributes.py", line 721, in get
value = self.callable_(state, passive)
File ".../sqlalchemy/orm/strategies.py", line 710, in _load_for_state
% (orm_util.state_str(state), self.key)
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <UserRepoToPerm at ...> is not bound to a Session; lazy load operation of attribute 'repository' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3)
Permissions are cached between requests: SA result records are stored in in
beaker.cache.sql_cache_short and resued in following requests after the initial
session as been removed. References in Permission objects would usually give
lazy lookup ... but not outside the original session, where we would get an
error like this.
Permissions are indeed implemented/used incorrectly. That might explain a part
of the problem. Even if not fully explaining or fixing this problem, it is
still worth fixing:
Permissions are fetched from the database using Session().query with multiple
class/table names (joined together in way that happens to match the references
specified in the table definitions) - including Repository. The results are
thus "structs" with selected objects. If repositories always were retrieved
using this selected repository, everything would be fine. In some places, this
was what we did.
But in some places, the code happened to do what was more intuitive: just use
.repository and rely on "lazy" resolving. SA was not aware that this one
already was present in the result struct, and would try to fetch it again. Best
case, that could be inefficient. Worst case, it would fail as we see here.
Fix this by only querying from one table but use the "joinedload" option to
also fetch other referenced tables in the same select. (This might
inefficiently return the main record multiple times ... but that was already
the case with the previous approach.)
This change is thus doing multiple things with circular dependencies that can't
be split up in minor parts without taking detours:
The existing repository join like:
.join((Repository, UserGroupRepoToPerm.repository_id == Repository.repo_id))
is thus replaced by:
.options(joinedload(UserGroupRepoToPerm.repository))
Since we only are doing Session.query() on one table, the results will be of
that type instead of "structs" with multiple objects. If only querying for
UserRepoToPerm this means:
- perm.UserRepoToPerm.repository becomes perm.repository
- perm.Permission.permission_name looked at the explicitly queried Permission
in the result struct - instead it should look in the the dereferenced
repository as perm.permission.permission_name
There has been reports of spurious crashes on resolving references like
.repository from Permissions:
File ".../kallithea/lib/auth.py", line 678, in __wrapper
if self.check_permissions(user):
File ".../kallithea/lib/auth.py", line 718, in check_permissions
return user.has_repository_permission_level(repo_name, self.required_perm)
File ".../kallithea/lib/auth.py", line 450, in has_repository_permission_level
actual_perm = self.permissions['repositories'].get(repo_name)
File ".../kallithea/lib/vcs/utils/lazy.py", line 41, in __get__
value = self._func(obj)
File ".../kallithea/lib/auth.py", line 442, in permissions
return self.__get_perms(user=self, cache=False)
File ".../kallithea/lib/auth.py", line 498, in __get_perms
return compute(user_id, user_is_admin)
File ".../kallithea/lib/auth.py", line 190, in _cached_perms_data
r_k = perm.UserRepoToPerm.repository.repo_name
File ".../sqlalchemy/orm/attributes.py", line 285, in __get__
return self.impl.get(instance_state(instance), dict_)
File ".../sqlalchemy/orm/attributes.py", line 721, in get
value = self.callable_(state, passive)
File ".../sqlalchemy/orm/strategies.py", line 710, in _load_for_state
% (orm_util.state_str(state), self.key)
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <UserRepoToPerm at ...> is not bound to a Session; lazy load operation of attribute 'repository' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3)
Permissions are cached between requests: SA result records are stored in in
beaker.cache.sql_cache_short and resued in following requests after the initial
session as been removed. References in Permission objects would usually give
lazy lookup ... but not outside the original session, where we would get an
error like this.
Permissions are indeed implemented/used incorrectly. That might explain a part
of the problem. Even if not fully explaining or fixing this problem, it is
still worth fixing:
Permissions are fetched from the database using Session().query with multiple
class/table names (joined together in way that happens to match the references
specified in the table definitions) - including Repository. The results are
thus "structs" with selected objects. If repositories always were retrieved
using this selected repository, everything would be fine. In some places, this
was what we did.
But in some places, the code happened to do what was more intuitive: just use
.repository and rely on "lazy" resolving. SA was not aware that this one
already was present in the result struct, and would try to fetch it again. Best
case, that could be inefficient. Worst case, it would fail as we see here.
Fix this by only querying from one table but use the "joinedload" option to
also fetch other referenced tables in the same select. (This might
inefficiently return the main record multiple times ... but that was already
the case with the previous approach.)
This change is thus doing multiple things with circular dependencies that can't
be split up in minor parts without taking detours:
The existing repository join like:
.join((Repository, UserGroupRepoToPerm.repository_id == Repository.repo_id))
is thus replaced by:
.options(joinedload(UserGroupRepoToPerm.repository))
Since we only are doing Session.query() on one table, the results will be of
that type instead of "structs" with multiple objects. If only querying for
UserRepoToPerm this means:
- perm.UserRepoToPerm.repository becomes perm.repository
- perm.Permission.permission_name looked at the explicitly queried Permission
in the result struct - instead it should look in the the dereferenced
repository as perm.permission.permission_name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b e285bb7abb28 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b ef60ae4a34ee 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 4f6a90fe63a1 4f6a90fe63a1 4f6a90fe63a1 4f6a90fe63a1 e285bb7abb28 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b dcce2a16e08d 5f481e4e888b e285bb7abb28 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b 5f481e4e888b | /**
* Sphinx stylesheet -- default theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
hr{
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.8em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #577632;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.80em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
div.sphinxsidebar input[type=image] {
border: 0;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.2em;
margin: 1.5em 0 1.5em 0;
box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
padding: 1px 2px;
font-size: 1.2em;
font-family: monospace;
}
|