-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: rename "Capability" to "Role", attach ID #462
Changes from 1 commit
20541ab
ce304b3
b8742e4
885071e
f24c85e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
import { TypedEmitter } from 'tiny-typed-emitter' | ||
import { InviteResponse_Decision } from './generated/rpc.js' | ||
import { projectKeyToId } from './utils.js' | ||
import { DEFAULT_CAPABILITIES } from './capabilities.js' | ||
import { ROLES } from './roles.js' | ||
|
||
/** @typedef {import('./datatype/index.js').DataType<import('./datastore/index.js').DataStore<'config'>, typeof import('./schema/project.js').deviceInfoTable, "deviceInfo", import('@mapeo/schema').DeviceInfo, import('@mapeo/schema').DeviceInfoValue>} DeviceInfoDataType */ | ||
/** @typedef {import('./datatype/index.js').DataType<import('./datastore/index.js').DataStore<'config'>, typeof import('./schema/client.js').projectSettingsTable, "projectSettings", import('@mapeo/schema').ProjectSettings, import('@mapeo/schema').ProjectSettingsValue>} ProjectDataType */ | ||
/** @typedef {{ deviceId: string, name?: import('@mapeo/schema').DeviceInfo['name'], capabilities: import('./capabilities.js').Capability }} MemberInfo */ | ||
/** @typedef {{ deviceId: string, name?: import('@mapeo/schema').DeviceInfo['name'], role: import('./roles.js').Role }} MemberInfo */ | ||
|
||
export class MemberApi extends TypedEmitter { | ||
#ownDeviceId | ||
#capabilities | ||
#roles | ||
#coreOwnership | ||
#encryptionKeys | ||
#projectKey | ||
|
@@ -19,7 +19,7 @@ export class MemberApi extends TypedEmitter { | |
/** | ||
* @param {Object} opts | ||
* @param {string} opts.deviceId public key of this device as hex string | ||
* @param {import('./capabilities.js').Capabilities} opts.capabilities | ||
* @param {import('./roles.js').Roles} opts.roles | ||
* @param {import('./core-ownership.js').CoreOwnership} opts.coreOwnership | ||
* @param {import('./generated/keys.js').EncryptionKeys} opts.encryptionKeys | ||
* @param {Buffer} opts.projectKey | ||
|
@@ -30,7 +30,7 @@ export class MemberApi extends TypedEmitter { | |
*/ | ||
constructor({ | ||
deviceId, | ||
capabilities, | ||
roles, | ||
coreOwnership, | ||
encryptionKeys, | ||
projectKey, | ||
|
@@ -39,7 +39,7 @@ export class MemberApi extends TypedEmitter { | |
}) { | ||
super() | ||
this.#ownDeviceId = deviceId | ||
this.#capabilities = capabilities | ||
this.#roles = roles | ||
this.#coreOwnership = coreOwnership | ||
this.#encryptionKeys = encryptionKeys | ||
this.#projectKey = projectKey | ||
|
@@ -51,15 +51,15 @@ export class MemberApi extends TypedEmitter { | |
* @param {string} deviceId | ||
* | ||
* @param {Object} opts | ||
* @param {import('./capabilities.js').RoleId} opts.roleId | ||
* @param {import('./roles.js').RoleIdAssignableToOthers} opts.roleId | ||
* @param {string} [opts.roleName] | ||
* @param {string} [opts.roleDescription] | ||
* @param {number} [opts.timeout] | ||
* | ||
* @returns {Promise<import('./generated/rpc.js').InviteResponse_Decision>} | ||
*/ | ||
async invite(deviceId, { roleId, roleName, roleDescription, timeout }) { | ||
if (!DEFAULT_CAPABILITIES[roleId]) { | ||
if (!ROLES[roleId]) { | ||
throw new Error('Invalid role id') | ||
} | ||
|
||
|
@@ -82,14 +82,14 @@ export class MemberApi extends TypedEmitter { | |
projectKey: this.#projectKey, | ||
encryptionKeys: this.#encryptionKeys, | ||
projectInfo: { name: project.name }, | ||
roleName: roleName || DEFAULT_CAPABILITIES[roleId].name, | ||
roleName: roleName || ROLES[roleId].name, | ||
roleDescription, | ||
invitorName: deviceName, | ||
timeout, | ||
}) | ||
|
||
if (response === InviteResponse_Decision.ACCEPT) { | ||
await this.#capabilities.assignRole(deviceId, roleId) | ||
await this.#roles.assignRole(deviceId, roleId) | ||
} | ||
|
||
return response | ||
|
@@ -100,10 +100,10 @@ export class MemberApi extends TypedEmitter { | |
* @returns {Promise<MemberInfo>} | ||
*/ | ||
async getById(deviceId) { | ||
const capabilities = await this.#capabilities.getCapabilities(deviceId) | ||
const role = await this.#roles.getRole(deviceId) | ||
|
||
/** @type {MemberInfo} */ | ||
const result = { deviceId, capabilities } | ||
const result = { deviceId, role } | ||
|
||
try { | ||
const configCoreId = await this.#coreOwnership.getCoreId( | ||
|
@@ -129,15 +129,15 @@ export class MemberApi extends TypedEmitter { | |
* @returns {Promise<Array<MemberInfo>>} | ||
*/ | ||
async getMany() { | ||
const [allCapabilities, allDeviceInfo] = await Promise.all([ | ||
this.#capabilities.getAll(), | ||
const [allRoles, allDeviceInfo] = await Promise.all([ | ||
this.#roles.getAll(), | ||
this.#dataTypes.deviceInfo.getMany(), | ||
]) | ||
|
||
return Promise.all( | ||
Object.entries(allCapabilities).map(async ([deviceId, capabilities]) => { | ||
Object.entries(allRoles).map(async ([deviceId, role]) => { | ||
/** @type {MemberInfo} */ | ||
const memberInfo = { deviceId, capabilities } | ||
const memberInfo = { deviceId, role } | ||
|
||
try { | ||
const configCoreId = await this.#coreOwnership.getCoreId( | ||
|
@@ -163,10 +163,10 @@ export class MemberApi extends TypedEmitter { | |
|
||
/** | ||
* @param {string} deviceId | ||
* @param {import('./capabilities.js').RoleId} roleId | ||
* @param {import('./roles.js').RoleIdAssignableToOthers} roleId | ||
* @returns {Promise<void>} | ||
*/ | ||
async assignRole(deviceId, roleId) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a TODO note here or open an issue to have stricter runtime checks here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also in the future we might want to add options to how we block users (which internally we might implement as different roles, or additional fields on membership records - maybe the latter better for many scenarios), for example:
Having a separate API to remove devices would be helpful for implementing these. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a stricter runtime check in f24c85e. Let me know if you still want me to add a TODO/issue. |
||
return this.#capabilities.assignRole(deviceId, roleId) | ||
return this.#roles.assignRole(deviceId, roleId) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be stricter now, since we do not want to allow inviting someone as a project creator. This should be the "assignable to others" role list, although we should probably exclude the blocked role from that, but maybe as a to-do because I think some tests invite as blocked, just because I was lazy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in f24c85e.