Extend Account Search API to include more information besides the ID
Summary
Follow up to https://github.com/TheThingsNetwork/lorawan-stack/pull/6162/#discussion_r1272433615 in the contacts PR.
Extend the API to also return the entity name.
Current Situation
Currently the searchAccounts API returns only the account ID.
Why do we need this? Who uses it, and when?
Would be nice to also have access to the entity name, for example, through this API.
Proposed Implementation
No response
Contributing
- [ ] I can help by doing more research.
- [ ] I can help by implementing the feature after the proposal above is approved.
- [X] I can help by testing the feature before it's released.
Code of Conduct
- [X] I agree to follow TTN's Community Code of Conduct.
more information besides the ID
@ryaplots: What additional information do you need?
more information besides the ID
@ryaplots: What additional information do you need?
So right now the searchAccounts API returns only the account ID. Would be nice if it returned, the attributes as well (name and description)
The context here is that accounts are polymorphic entities - they are either users or organizations. It is possible search accounts, but the only thing which is returned back will be the identifiers for the entity.
The use case here is that organizations or users generally have a name which would be helpful to be rendered when one tries to add someone as a collaborator or contact to an entity - if you need a clear mental image, think of the Github 'invite member' screen: you see both their name and their account ID.
The common fields are:
created_atupdated_atdeleted_atnamedescriptionattributes
Not all of these fields are public, so for non-admin users we need to be careful on how we handle them. Luckily the baseline work has been done already - we have the public paths and can filter with them:
https://github.com/TheThingsNetwork/lorawan-stack/blob/894c503de81b6a9a362be4621d593baef2edba4c/pkg/ttnpb/public.go#L139-L158 https://github.com/TheThingsNetwork/lorawan-stack/blob/894c503de81b6a9a362be4621d593baef2edba4c/pkg/ttnpb/public.go#L120-L137
The conditions upon which to filter also exist in SearchUser/SearchOrganization:
https://github.com/TheThingsNetwork/lorawan-stack/blob/894c503de81b6a9a362be4621d593baef2edba4c/pkg/identityserver/registry_search.go#L371-L378
So the task looks as follows:
- Add a field mask to
SearchAccountsRequest. - Add a common fields message to
SearchAccountsResponse, containing the common fields depending on the rights of the calling user. Add arepeatedfield for the account fields. - Add support in the storage layer (
bunstore) to join the original table and retrieve these attributes. - Filter them out at RPC layer. If the caller is not an admin we shouldn't even pass the fields to the storage layer in order to avoid doing joins for no reason.
The response message can look something like:
message SearchAccountsResponse {
repeated OrganizationOrUserIdentifiers account_ids = 1;
message Account {
option (thethings.flags.message) = {
select: true,
set: false
};
// The identifiers of the account. These are public and can be seen by any authenticated user in the network.
oneof ids {
option (validate.required) = true;
OrganizationIdentifiers organization_ids = 1;
UserIdentifiers user_ids = 2;
}
// When the account was created. This information is public and can be seen by any authenticated user in the network.
google.protobuf.Timestamp created_at = 3 [(thethings.flags.field) = {
select: false,
set: false
}];
// When the account was last updated. This information is public and can be seen by any authenticated user in the network.
google.protobuf.Timestamp updated_at = 4 [(thethings.flags.field) = {
select: false,
set: false
}];
// When the account was deleted. This information is public and can be seen by any authenticated user in the network.
google.protobuf.Timestamp deleted_at = 5 [(thethings.flags.field) = {
select: true,
set: false
}];
// The name of the account. This information is public and can be seen by any authenticated user in the network.
string name = 6 [(validate.rules).string.max_len = 50];
// A description for the account. This information is public for user accounts and can be seen by any authenticated user in the network.
string description = 7 [(validate.rules).string.max_len = 2000];
// Key-value attributes for this account.
map<string, string> attributes = 8 [(validate.rules).map = {
max_pairs: 10,
keys: {
string: {
pattern: "^[a-z0-9](?:[-]?[a-z0-9]){2,}$",
max_len: 36
}
},
values: {
string: {max_len: 200}
}
}];
}
repeated Account accounts = 2;
}