diff --git a/app/src/app/admin.service.ts b/app/src/app/admin.service.ts index 1c33c04..ba58e22 100644 --- a/app/src/app/admin.service.ts +++ b/app/src/app/admin.service.ts @@ -8,6 +8,7 @@ export class AdminService { readonly #APPS: { [key: string]: string } = { registries: 'did:dht:jtubj7jooigmx9y7dz13j9kxhoy3pyo6jzizh3irkmwity3saxko', + communities: 'did:dht:jtubj7jooigmx9y7dz13j9kxhoy3pyo6jzizh3irkmwity3saxko', }; readonly #ADMIN_DIDS: string[] = [ diff --git a/app/src/app/admin/admin.component.html b/app/src/app/admin/admin.component.html index 778af41..3554cee 100644 --- a/app/src/app/admin/admin.component.html +++ b/app/src/app/admin/admin.component.html @@ -3,9 +3,20 @@

Communities

- + +
+
+

Owners

+ + + + @if (roles() && roles().length > 0) { +

User's with roles:

+ @for(role of roles(); track role) { +
{{ role }}
+ } }
@@ -25,7 +36,7 @@

Admins

Owners

- + @if (roles() && roles().length > 0) {

User's with roles:

diff --git a/app/src/app/admin/admin.component.ts b/app/src/app/admin/admin.component.ts index 0ed6bfe..ac665aa 100644 --- a/app/src/app/admin/admin.component.ts +++ b/app/src/app/admin/admin.component.ts @@ -9,6 +9,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { HttpClient } from '@angular/common/http'; import { registry } from '../../protocols'; +import { community } from '../../protocols'; import { AdminService } from '../admin.service'; import { LayoutService } from '../layout.service'; import { IdentityService } from '../identity.service'; @@ -102,9 +103,15 @@ export class AdminComponent { } } - async givePermissions() { + async givePermissionsToRegistry() { for (let did of this.admin.getAdminDids()) { - await this.givePermission(did); + await this.givePermissionToCommunity(did); + } + } + + async givePermissionsToCommunity() { + for (let did of this.admin.getAdminDids()) { + await this.givePermissionToCommunity(did); } } @@ -184,7 +191,7 @@ export class AdminComponent { // } } - async givePermission(did: string) { + async givePermissionToRegistry(did: string) { // Assign collaborator role to the DID. const tags = { role: true, @@ -237,6 +244,59 @@ export class AdminComponent { console.log('Role record:', roleRecord); } + async givePermissionToCommunity(did: string) { + // Assign collaborator role to the DID. + const tags = { + role: true, + }; + + // const query = { + // data: {}, + // message: { + // tags: tags, + // recipient: collaborator, + // protocol: taskDefinition.protocol, + // parentContextId: record.contextId, // Make the role a child of the list. + // // protocolPath: 'list/collaborator', + // protocolPath: 'list/collaborator', + // schema: taskDefinition.types.collaborator.schema, + // // dataFormat: taskDefinition.types.collaborator.dataFormats[0], + // }, + // }; + + const query = { + store: false, + data: {}, + message: { + tags: tags, + recipient: did, + protocol: community.uri, + // parentContextId: record.contextId, // Make the role a child of the list. + // protocolPath: 'list/collaborator', + schema: 'https://schema.ariton.app/community/globalAdmin', + protocolPath: 'globalAdmin', + // protocolRole: 'profile/admin', + // schema: registry.definition.types.profile.dataFormats.types.collaborator.schema, + // dataFormat: taskDefinition.types.collaborator.dataFormats[0], + }, + }; + + console.log('QUERY:', query); + + // This will fail if the DID already have a role assigned. + // TODO: Implement a query to see if the user already has role assigned and skip this step. + const { record: roleRecord, status: roleStatus } = await this.identity.web5.dwn.records.create(query); + + const ownerDid = this.admin.getIdentifierForApp('communities'); + const { status: sendStatus } = await roleRecord!.send(ownerDid); + + console.log('Send status:', sendStatus); + + console.log('!!!!!'); + console.log('Role status:', roleStatus); + console.log('Role record:', roleRecord); + } + async deleteRegistries() { const did = this.admin.getIdentifierForApp('registries'); diff --git a/app/src/app/app.routes.ts b/app/src/app/app.routes.ts index 167883e..e2cb3a3 100644 --- a/app/src/app/app.routes.ts +++ b/app/src/app/app.routes.ts @@ -61,6 +61,12 @@ export const routes: Routes = [ title: 'Communities', data: { hide: true, icon: 'diversity_2' }, }, + { + path: 'community/:id/:did', + loadComponent: () => import('./community/community.component').then((c) => c.CommunityComponent), + title: 'Communities', + data: { hide: true, icon: 'diversity_2' }, + }, { path: 'friends', loadComponent: () => import('./friends/friends.component').then((c) => c.FriendsComponent), diff --git a/app/src/app/community/community.component.html b/app/src/app/community/community.component.html index 052d103..bd497a2 100644 --- a/app/src/app/community/community.component.html +++ b/app/src/app/community/community.component.html @@ -45,6 +45,20 @@ + + @if (admin.isAdmin(identity.did)) { + + + Administration + + + + + + + }
diff --git a/app/src/app/community/community.component.ts b/app/src/app/community/community.component.ts index dfbc739..64c6366 100644 --- a/app/src/app/community/community.component.ts +++ b/app/src/app/community/community.component.ts @@ -17,6 +17,8 @@ import { RecordEntry } from '../data'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { ProfileHeaderComponent } from '../shared/components/profile-header/profile-header.component'; +import { AdminService } from '../admin.service'; +import { IdentityService } from '../identity.service'; @Component({ selector: 'app-community', @@ -53,10 +55,16 @@ export class CommunityComponent { data = inject(DataService); + admin = inject(AdminService); + + identity = inject(IdentityService); + selectedCommunity = signal(null); community = signal | null>(null); + searchingMembers = signal(false); + constructor() { effect(async () => { if (this.app.initialized() && this.selectedCommunity()) { @@ -65,6 +73,8 @@ export class CommunityComponent { }); } + did = ''; + ngOnInit() { this.layout.marginOff(); @@ -72,8 +82,11 @@ export class CommunityComponent { this.layout.resetActions(); const id = params.get('id'); + const did = params.get('did'); + this.did = did || ''; console.log('Loading community: ', id); + console.log('Loading owner: ', did); if (!id || id == ':id' || id == 'home') { this.selectedCommunity.set(null); @@ -106,7 +119,12 @@ export class CommunityComponent { this.photos.set(photos); } - searchingMembers = signal(false); + async publishCommunity() { + const result = await this.community()?.record.import(); + // const result = await this.community()?.record.send(this.admin.getIdentifierForApp('communities')); + console.log('Community import status: ', result); + console.log('Publish community'); + } searchMembers() { this.searchingMembers.set(true); @@ -118,7 +136,7 @@ export class CommunityComponent { } async loadCommunity() { - const entry = await this.data.get(this.selectedCommunity()!); + const entry = await this.data.get(this.selectedCommunity()!, this.did); this.community.set(entry); } } diff --git a/app/src/app/data.service.ts b/app/src/app/data.service.ts index 0841d13..d10410b 100644 --- a/app/src/app/data.service.ts +++ b/app/src/app/data.service.ts @@ -39,8 +39,8 @@ export class DataService { return this.app.storage.load(this.configuration, tags); } - async get(recordId: string) { - return this.app.storage.get(recordId); + async get(recordId: string, from: string | null = null) { + return this.app.storage.get(recordId, from); } async update(record: Record, data: any, tags: any, published = false) { diff --git a/app/src/app/storage.service.ts b/app/src/app/storage.service.ts index bb138df..642cd26 100644 --- a/app/src/app/storage.service.ts +++ b/app/src/app/storage.service.ts @@ -73,8 +73,14 @@ export class StorageService { return list; } - async get(recordId: string) { - var { record, status } = await this.identity.web5.dwn.records.read({ message: { filter: { recordId } } }); + async get(recordId: string, from: string | null = null) { + let query: any = { message: { filter: { recordId } } }; + + if (from) { + query.from = from; + } + + var { record, status } = await this.identity.web5.dwn.records.read(query); if (status.code !== 200) { throw new Error(`Failed to get data (${status.code}): ${status.detail}`); diff --git a/app/src/protocols/community.ts b/app/src/protocols/community.ts index 6f52ae8..93f35ca 100644 --- a/app/src/protocols/community.ts +++ b/app/src/protocols/community.ts @@ -27,38 +27,37 @@ export const protocolDefinition = { dataFormats: ['text/plain'], }, globalAdmin: { - schema: 'https://schema.ariton.app/community/schema/globalAdmin', + schema: 'https://schema.ariton.app/community/globalAdmin', dataFormats: ['application/json'], }, admin: { - schema: 'https://schema.ariton.app/community/schema/admin', + schema: 'https://schema.ariton.app/community/admin', dataFormats: ['application/json'], }, }, structure: { globalAdmin: { $role: true, + $actions: [ + { + role: 'globalAdmin', + can: ['create', 'read', 'update', 'query', 'subscribe', 'co-update', 'co-delete'], + }, + ], }, friend: { $role: true, }, community: { $actions: [ - { - role: 'globalAdmin', - can: ['create', 'update'], - - //can: ['create', 'read', 'update', 'delete', 'prune', 'co-prune', 'co-delete', 'co-update'], - }, + { role: 'globalAdmin', can: ['create', 'read', 'update', 'query', 'subscribe', 'co-update', 'co-delete'] }, ], - admin: { $role: true, $actions: [ { role: 'globalAdmin', - can: ['create', 'update'], - + can: ['create', 'read', 'update', 'query', 'subscribe', 'co-update', 'co-delete'], //can: ['create', 'read', 'update', 'delete', 'prune', 'co-prune', 'co-delete', 'co-update'], }, ],