NSF record share perms → structured data + compact text. Uses warmed ``nested_share_record_share_cache``. Direct (non-inherited) accessors win over folder-inherited rows for the same identity. When the record ACL cache is empty, falls back to the parent NSF folder ACL.
(params, record_uid, *, include_uids=False)
| 2229 | |
| 2230 | |
| 2231 | def _nsf_record_share_data(params, record_uid, *, include_uids=False): |
| 2232 | """NSF record share perms → structured data + compact text. |
| 2233 | |
| 2234 | Uses warmed ``nested_share_record_share_cache``. Direct (non-inherited) |
| 2235 | accessors win over folder-inherited rows for the same identity. When the |
| 2236 | record ACL cache is empty, falls back to the parent NSF folder ACL. |
| 2237 | """ |
| 2238 | from .. import nested_share_folder as _nsf |
| 2239 | accessors = list(_nsf.get_nsf_record_share_accessors(params, record_uid) or []) |
| 2240 | if not accessors: |
| 2241 | try: |
| 2242 | parent_uids = _nsf.find_nested_share_folders_for_record(params, record_uid) or [] |
| 2243 | except Exception as exc: |
| 2244 | logging.debug('NSF parent folder lookup failed for %s: %s', record_uid, exc) |
| 2245 | parent_uids = [] |
| 2246 | for fuid in parent_uids: |
| 2247 | data, text = _nsf_folder_share_data(params, fuid, include_uids=include_uids) |
| 2248 | if data: |
| 2249 | return data, text |
| 2250 | return None, '' |
| 2251 | |
| 2252 | # Direct shares first so inherited folder rows do not hide them. |
| 2253 | accessors.sort(key=lambda a: 1 if a.get('inherited') else 0) |
| 2254 | |
| 2255 | users = [] |
| 2256 | teams = [] |
| 2257 | applications = [] |
| 2258 | user_parts = [] |
| 2259 | team_parts = [] |
| 2260 | app_parts = [] |
| 2261 | seen_users = set() |
| 2262 | seen_teams = set() |
| 2263 | seen_apps = set() |
| 2264 | |
| 2265 | for a in accessors: |
| 2266 | at = a.get('access_type') or '' |
| 2267 | abbrev = _nsf_role_abbrev(a) |
| 2268 | auid = a.get('access_type_uid') or a.get('accessor_uid') or '' |
| 2269 | |
| 2270 | if a.get('owner') or at == 'AT_OWNER': |
| 2271 | email = (a.get('accessor_name') or '').strip() |
| 2272 | if email and _looks_like_uid(email): |
| 2273 | email = '' |
| 2274 | if not email: |
| 2275 | email = _resolve_nsf_user_email(params, { |
| 2276 | 'username': a.get('accessor_name') or a.get('username'), |
| 2277 | 'accessor_uid': auid, |
| 2278 | }) |
| 2279 | if email and email.lower() not in seen_users: |
| 2280 | users.append({'email': email, 'permissions': ['OW']}) |
| 2281 | user_parts.append(f'[{email}:OW]') |
| 2282 | seen_users.add(email.lower()) |
| 2283 | elif not email and include_uids and auid and auid not in seen_users: |
| 2284 | users.append({'uid': auid, 'permissions': ['OW']}) |
| 2285 | user_parts.append(f'[{auid}:OW]') |
| 2286 | seen_users.add(auid) |
| 2287 | continue |
| 2288 |