feat: mark us as admin and others as invite pending

pull/2873/head
Audric Ackermann 2 years ago
parent 197383a52f
commit 9191c3476d

@ -12,6 +12,7 @@ import { StateType } from '../state/reducer';
import { getMessageReactsProps } from '../state/selectors/conversations'; import { getMessageReactsProps } from '../state/selectors/conversations';
import { useLibGroupAdmins, useLibGroupMembers, useLibGroupName } from '../state/selectors/groups'; import { useLibGroupAdmins, useLibGroupMembers, useLibGroupName } from '../state/selectors/groups';
import { isPrivateAndFriend } from '../state/selectors/selectedConversation'; import { isPrivateAndFriend } from '../state/selectors/selectedConversation';
import { useOurPkStr } from '../state/selectors/user';
export function useAvatarPath(convoId: string | undefined) { export function useAvatarPath(convoId: string | undefined) {
const convoProps = useConversationPropsById(convoId); const convoProps = useConversationPropsById(convoId);
@ -148,8 +149,9 @@ export function useIsKickedFromGroup(convoId?: string) {
} }
export function useWeAreAdmin(convoId?: string) { export function useWeAreAdmin(convoId?: string) {
const convoProps = useConversationPropsById(convoId); const groupAdmins = useGroupAdmins(convoId);
return Boolean(convoProps && convoProps.weAreAdmin); const us = useOurPkStr();
return Boolean(groupAdmins.includes(us));
} }
export function useGroupAdmins(convoId?: string) { export function useGroupAdmins(convoId?: string) {
@ -221,7 +223,8 @@ export function useIsOutgoingRequest(convoId?: string) {
} }
/** /**
* Not to be exported: This selector is too generic and needs to be broken node in individual fields selectors. * Note: NOT to be exported:
* This selector is too generic and needs to be broken node in individual fields selectors.
* Make sure when writing a selector that you fetch the data from libsession if needed. * Make sure when writing a selector that you fetch the data from libsession if needed.
* (check useSortedGroupMembers() as an example) * (check useSortedGroupMembers() as an example)
*/ */

@ -42,9 +42,6 @@ async function handleGroupSharedConfigMessages(
groupKeys: keys, groupKeys: keys,
groupMember: members, groupMember: members,
}; };
console.info(
`groupInfo before merge: ${stringify(await MetaGroupWrapperActions.infoGet(groupPk))}`
);
await MetaGroupWrapperActions.metaMerge(groupPk, toMerge); await MetaGroupWrapperActions.metaMerge(groupPk, toMerge);
await LibSessionUtil.saveMetaGroupDumpToDb(groupPk); await LibSessionUtil.saveMetaGroupDumpToDb(groupPk);

@ -1,4 +1,4 @@
import _ from 'lodash'; import _, { concat } from 'lodash';
import { ClosedGroup, getMessageQueue } from '..'; import { ClosedGroup, getMessageQueue } from '..';
import { ConversationTypeEnum } from '../../models/conversationAttributes'; import { ConversationTypeEnum } from '../../models/conversationAttributes';
import { addKeyPairToCacheAndDBIfNeeded } from '../../receiver/closedGroups'; import { addKeyPairToCacheAndDBIfNeeded } from '../../receiver/closedGroups';
@ -26,10 +26,14 @@ import { groupInfoActions } from '../../state/ducks/groups';
*/ */
export async function createClosedGroup(groupName: string, members: Array<string>, isV3: boolean) { export async function createClosedGroup(groupName: string, members: Array<string>, isV3: boolean) {
if (isV3) { if (isV3) {
const us = UserUtils.getOurPubKeyStrFromCache();
// we need to send a group info and encryption keys message to the batch endpoint with both seqno being 0 // we need to send a group info and encryption keys message to the batch endpoint with both seqno being 0
console.error('isV3 send invite to group TODO'); // FIXME console.error('isV3 send invite to group TODO'); // FIXME
// FIXME we should save the key to the wrapper right away? or even to the DB idk // FIXME we should save the key to the wrapper right away? or even to the DB idk
window.inboxStore.dispatch(groupInfoActions.initNewGroupInWrapper({ members, groupName })); window.inboxStore.dispatch(
groupInfoActions.initNewGroupInWrapper({ members: concat(members, [us]), groupName, us })
);
return; return;
} }

@ -1,6 +1,6 @@
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { GroupInfoGet, GroupMemberGet, GroupPubkeyType } from 'libsession_util_nodejs'; import { GroupInfoGet, GroupMemberGet, GroupPubkeyType } from 'libsession_util_nodejs';
import { isEmpty } from 'lodash'; import { isEmpty, uniq } from 'lodash';
import { ConfigDumpData } from '../../data/configDump/configDump'; import { ConfigDumpData } from '../../data/configDump/configDump';
import { ConversationTypeEnum } from '../../models/conversationAttributes'; import { ConversationTypeEnum } from '../../models/conversationAttributes';
import { HexString } from '../../node/hexStrings'; import { HexString } from '../../node/hexStrings';
@ -16,6 +16,7 @@ import {
MetaGroupWrapperActions, MetaGroupWrapperActions,
UserGroupsWrapperActions, UserGroupsWrapperActions,
} from '../../webworker/workers/browser/libsession_worker_interface'; } from '../../webworker/workers/browser/libsession_worker_interface';
import { PreConditionFailed } from '../../session/utils/errors';
export type GroupState = { export type GroupState = {
infos: Record<GroupPubkeyType, GroupInfoGet>; infos: Record<GroupPubkeyType, GroupInfoGet>;
@ -35,12 +36,23 @@ type GroupDetailsUpdate = {
const initNewGroupInWrapper = createAsyncThunk( const initNewGroupInWrapper = createAsyncThunk(
'group/initNewGroupInWrapper', 'group/initNewGroupInWrapper',
async (groupDetails: { async ({
groupName,
members,
us,
}: {
groupName: string; groupName: string;
members: Array<string>; members: Array<string>;
us: string;
}): Promise<GroupDetailsUpdate> => { }): Promise<GroupDetailsUpdate> => {
if (!members.includes(us)) {
throw new PreConditionFailed('initNewGroupInWrapper needs us to be a member');
}
const uniqMembers = uniq(members);
try { try {
const newGroup = await UserGroupsWrapperActions.createGroup(); const newGroup = await UserGroupsWrapperActions.createGroup();
const groupPk = newGroup.pubkeyHex;
newGroup.name = groupName; // this will be used by the linked devices until they fetch the info from the groups swarm
await UserGroupsWrapperActions.setGroup(newGroup); await UserGroupsWrapperActions.setGroup(newGroup);
@ -49,47 +61,42 @@ const initNewGroupInWrapper = createAsyncThunk(
throw new Error('Current user has no priv ed25519 key?'); throw new Error('Current user has no priv ed25519 key?');
} }
const userEd25519Secretkey = ourEd25519KeypairBytes.privKeyBytes; const userEd25519Secretkey = ourEd25519KeypairBytes.privKeyBytes;
const groupEd2519Pk = HexString.fromHexString(newGroup.pubkeyHex).slice(1); // remove the 03 prefix (single byte once in hex form) const groupEd2519Pk = HexString.fromHexString(groupPk).slice(1); // remove the 03 prefix (single byte once in hex form)
// dump is always empty when creating a new groupInfo // dump is always empty when creating a new groupInfo
await MetaGroupWrapperActions.init(newGroup.pubkeyHex, { await MetaGroupWrapperActions.init(groupPk, {
metaDumped: null, metaDumped: null,
userEd25519Secretkey: toFixedUint8ArrayOfLength(userEd25519Secretkey, 64), userEd25519Secretkey: toFixedUint8ArrayOfLength(userEd25519Secretkey, 64),
groupEd25519Secretkey: newGroup.secretKey, groupEd25519Secretkey: newGroup.secretKey,
groupEd25519Pubkey: toFixedUint8ArrayOfLength(groupEd2519Pk, 32), groupEd25519Pubkey: toFixedUint8ArrayOfLength(groupEd2519Pk, 32),
}); });
await Promise.all( for (let index = 0; index < uniqMembers.length; index++) {
groupDetails.members.map(async member => { const member = uniqMembers[index];
const created = await MetaGroupWrapperActions.memberGetOrConstruct( const created = await MetaGroupWrapperActions.memberGetOrConstruct(groupPk, member);
newGroup.pubkeyHex, if (created.pubkeyHex === us) {
member await MetaGroupWrapperActions.memberSetPromoted(groupPk, created.pubkeyHex, false);
); } else {
await MetaGroupWrapperActions.memberSetInvited( await MetaGroupWrapperActions.memberSetInvited(groupPk, created.pubkeyHex, false);
newGroup.pubkeyHex, }
created.pubkeyHex, }
false
); const infos = await MetaGroupWrapperActions.infoGet(groupPk);
})
);
const infos = await MetaGroupWrapperActions.infoGet(newGroup.pubkeyHex);
if (!infos) { if (!infos) {
throw new Error( throw new Error(`getInfos of ${groupPk} returned empty result even if it was just init.`);
`getInfos of ${newGroup.pubkeyHex} returned empty result even if it was just init.`
);
} }
infos.name = groupDetails.groupName; infos.name = groupName;
await MetaGroupWrapperActions.infoSet(newGroup.pubkeyHex, infos); await MetaGroupWrapperActions.infoSet(groupPk, infos);
const members = await MetaGroupWrapperActions.memberGetAll(newGroup.pubkeyHex); const membersFromWrapper = await MetaGroupWrapperActions.memberGetAll(groupPk);
if (!members || isEmpty(members)) { if (!membersFromWrapper || isEmpty(membersFromWrapper)) {
throw new Error( throw new Error(
`memberGetAll of ${newGroup.pubkeyHex} returned empty result even if it was just init.` `memberGetAll of ${groupPk} returned empty result even if it was just init.`
); );
} }
const convo = await getConversationController().getOrCreateAndWait( const convo = await getConversationController().getOrCreateAndWait(
newGroup.pubkeyHex, groupPk,
ConversationTypeEnum.GROUPV3 ConversationTypeEnum.GROUPV3
); );
@ -99,11 +106,7 @@ const initNewGroupInWrapper = createAsyncThunk(
// // the sync below will need the secretKey of the group to be saved in the wrapper. So save it! // // the sync below will need the secretKey of the group to be saved in the wrapper. So save it!
await UserGroupsWrapperActions.setGroup(newGroup); await UserGroupsWrapperActions.setGroup(newGroup);
await GroupSync.queueNewJobIfNeeded(newGroup.pubkeyHex); await GroupSync.queueNewJobIfNeeded(groupPk);
// const us = UserUtils.getOurPubKeyStrFromCache();
// // Ensure the current user is a member and admin
// const members = uniq([...groupDetails.members, us]);
// const updateGroupDetails: ClosedGroup.GroupInfo = { // const updateGroupDetails: ClosedGroup.GroupInfo = {
// id: newGroup.pubkeyHex, // id: newGroup.pubkeyHex,
@ -122,7 +125,7 @@ const initNewGroupInWrapper = createAsyncThunk(
await convo.commit(); await convo.commit();
convo.updateLastMessage(); convo.updateLastMessage();
return { groupPk: newGroup.pubkeyHex, infos, members }; return { groupPk: newGroup.pubkeyHex, infos, members: membersFromWrapper };
} catch (e) { } catch (e) {
throw e; throw e;
} }

@ -4,6 +4,7 @@ import { LocalizerType } from '../../types/Util';
import { StateType } from '../reducer'; import { StateType } from '../reducer';
import { UserStateType } from '../ducks/user'; import { UserStateType } from '../ducks/user';
import { useSelector } from 'react-redux';
export const getUser = (state: StateType): UserStateType => state.user; export const getUser = (state: StateType): UserStateType => state.user;
@ -13,3 +14,7 @@ export const getOurNumber = createSelector(
); );
export const getIntl = createSelector(getUser, (): LocalizerType => window.i18n); export const getIntl = createSelector(getUser, (): LocalizerType => window.i18n);
export function useOurPkStr() {
return useSelector((state: StateType) => getOurNumber(state));
}

Loading…
Cancel
Save