Previously, these were 'star' links owned by the all users group.
However, the all users group is now a 'role' and new rule (since
issue #16007) is that 'role' groups cannot directly own things.
So now public favorites are defined as a link owned by the system user
with tail_uuid as the all users group.
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>
) { }
create(data: { userUuid: string; resource: { uuid: string; name: string } }) {
- return this.linkService.create({
- ownerUuid: data.userUuid,
+ const l = this.linkService.create({
+ // If this is for the all users group, it must be owned by
+ // the system user.
+ ownerUuid: (data.userUuid.substr(-22) === "-j7d0g-fffffffffffffff" ?
+ data.userUuid.substr(0, 5) + "-tpzed-000000000000000"
+ : data.userUuid),
tailUuid: data.userUuid,
headUuid: data.resource.uuid,
linkClass: LinkClass.STAR,
name: data.resource.name
});
+
+ if (data.userUuid.substr(-22) === "-j7d0g-fffffffffffffff") {
+ // If this is for the all users group, we need to create a
+ // permission link as well.
+ l.then(result =>
+ this.linkService.create({
+ tailUuid: data.userUuid,
+ headUuid: result.uuid,
+ linkClass: LinkClass.PERMISSION,
+ name: "can_read"
+ }));
+ }
+
+ return l;
}
delete(data: { userUuid: string; resourceUuid: string; }) {
return this.linkService
.list({
filters: new FilterBuilder()
- .addEqual('owner_uuid', data.userUuid)
+ .addEqual('tail_uuid', data.userUuid)
.addEqual('head_uuid', data.resourceUuid)
.addEqual('link_class', LinkClass.STAR)
.getFilters()
.list({
filters: new FilterBuilder()
.addIn("head_uuid", resourceUuids)
- .addEqual("owner_uuid", userUuid)
+ .addEqual("tail_uuid", userUuid)
.addEqual("link_class", LinkClass.STAR)
.getFilters()
})
import { getDataExplorerColumnFilters } from '~/store/data-explorer/data-explorer-middleware-service';
import { serializeSimpleObjectTypeFilters } from '../resource-type-filters/resource-type-filters';
import { ResourceKind } from "~/models/resource";
+import { LinkClass } from "~/models/link";
export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareService {
constructor(private services: ServiceRepository, id: string) {
api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
const responseLinks = await this.services.linkService.list({
filters: new FilterBuilder()
- .addEqual("link_class", 'star')
+ .addEqual("link_class", LinkClass.STAR)
.addEqual('tail_uuid', getUserUuid(api.getState()))
.addEqual('tail_kind', ResourceKind.USER)
.getFilters()
try {
api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
const uuidPrefix = api.getState().auth.config.uuidPrefix;
- const uuid = `${uuidPrefix}-j7d0g-fffffffffffffff`;
+ const systemUuid = `${uuidPrefix}-tpzed-000000000000000`;
+ const allusersUuid = `${uuidPrefix}-j7d0g-fffffffffffffff`;
const responseLinks = await this.services.linkService.list({
limit: dataExplorer.rowsPerPage,
offset: dataExplorer.page * dataExplorer.rowsPerPage,
filters: new FilterBuilder()
.addEqual('link_class', LinkClass.STAR)
.addILike("name", dataExplorer.searchValue)
- .addEqual('owner_uuid', uuid)
+ .addIn('owner_uuid', [allusersUuid, systemUuid])
+ .addEqual('tail_uuid', allusersUuid)
.addIsA("head_uuid", typeFilters)
.getFilters()
});
async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
const { pickerId, includeCollections = false, includeFiles = false } = params;
const uuidPrefix = getState().auth.config.uuidPrefix;
- const uuid = `${uuidPrefix}-j7d0g-fffffffffffffff`;
- if (uuid) {
+ const systemUuid = `${uuidPrefix}-tpzed-000000000000000`;
+ const allusersUuid = `${uuidPrefix}-j7d0g-fffffffffffffff`;
- const filters = pipe(
- (fb: FilterBuilder) => includeCollections
- ? fb.addIsA('head_uuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION])
- : fb.addIsA('head_uuid', [ResourceKind.PROJECT]),
- fb => fb
- .addEqual('link_class', LinkClass.STAR)
- .addEqual('owner_uuid', uuid)
- .getFilters(),
- )(new FilterBuilder());
+ const filters = pipe(
+ (fb: FilterBuilder) => includeCollections
+ ? fb.addIsA('head_uuid', [ResourceKind.PROJECT, ResourceKind.COLLECTION])
+ : fb.addIsA('head_uuid', [ResourceKind.PROJECT]),
+ fb => fb
+ .addEqual('link_class', LinkClass.STAR)
+ .addIn('owner_uuid', [systemUuid, allusersUuid])
+ .addEqual('tail_uuid', allusersUuid)
+ .getFilters(),
+ )(new FilterBuilder());
- const { items } = await services.linkService.list({ filters });
+ const { items } = await services.linkService.list({ filters });
- dispatch<any>(receiveTreePickerData<LinkResource>({
- id: 'Public Favorites',
- pickerId,
- data: items,
- extractNodeData: item => ({
- id: item.headUuid,
- value: item,
- status: item.headKind === ResourceKind.PROJECT
+ dispatch<any>(receiveTreePickerData<LinkResource>({
+ id: 'Public Favorites',
+ pickerId,
+ data: items,
+ extractNodeData: item => ({
+ id: item.headUuid,
+ value: item,
+ status: item.headKind === ResourceKind.PROJECT
+ ? TreeNodeStatus.INITIAL
+ : includeFiles
? TreeNodeStatus.INITIAL
- : includeFiles
- ? TreeNodeStatus.INITIAL
- : TreeNodeStatus.LOADED
- }),
- }));
- }
+ : TreeNodeStatus.LOADED
+ }),
+ }));
};
export const receiveTreePickerProjectsData = (id: string, projects: ProjectResource[], pickerId: string) =>