Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .mdeprc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if (os.platform() !== 'darwin') {
} catch (e) { }
}

exports.node = "20";
exports.node = "22.13.1";
exports.in_one = true;
exports.auto_compose = true;
exports.with_local_compose = true;
Expand Down
4 changes: 1 addition & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
FROM makeomatic/node:$NODE_VERSION

ENV NCONF_NAMESPACE=MS_USERS \
NODE_ENV=$NODE_ENV \
COREPACK_ENABLE_NETWORK=1
NODE_ENV=$NODE_ENV

WORKDIR /src

Expand All @@ -12,7 +11,6 @@ RUN \
apk --update --upgrade \
add ca-certificates --virtual .buildDeps git ca-certificates openssl g++ make python3 linux-headers \
&& update-ca-certificates \
&& corepack install -g pnpm@9 \
&& chown node:node /src \
&& su node sh -c "cd /src && pnpm fetch --prod" \
&& su node sh -c "rm -rf ~/.cache && pnpm store prune" \
Expand Down
13 changes: 7 additions & 6 deletions src/utils/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { HttpStatusError } = require('@microfleet/validation');
const challengeAct = require('./challenges/challenge');
const redisKey = require('./key');
const handlePipeline = require('./pipeline-error');
const { getInternalData, getUserId } = require('./userData');
const { getUserId } = require('./userData');
const {
USERS_CONTACTS,
USERS_DEFAULT_CONTACT,
Expand Down Expand Up @@ -64,11 +64,8 @@ async function removeAllEmailContactsOfUser(redisPipe, userId, exceptEmail) {
}
}

async function replaceUserName(redisPipe, userId, verifiedEmail) {
async function setUserName(redisPipe, userId, verifiedEmail) {
const { config: { jwt: { defaultAudience } } } = this;
const internalData = await getInternalData.call(this, userId);
const username = internalData[USERS_USERNAME_FIELD];
redisPipe.hdel(USERS_USERNAME_TO_ID, username);
Comment thread
o-v-t marked this conversation as resolved.
redisPipe.hset(USERS_USERNAME_TO_ID, verifiedEmail, userId);
redisPipe.hset(redisKey(userId, USERS_DATA), USERS_USERNAME_FIELD, verifiedEmail);
redisPipe.hset(redisKey(userId, USERS_METADATA, defaultAudience), USERS_USERNAME_FIELD, JSON.stringify(verifiedEmail));
Expand Down Expand Up @@ -176,7 +173,7 @@ async function verifyEmail({ secret }) {
await removeAllEmailContactsOfUser.call(this, pipe, userId, contact.value);
}
if (this.config.contacts.updateUsername) {
await replaceUserName.call(this, pipe, userId, contact.value);
await setUserName.call(this, pipe, userId, contact.value);
}
pipe.hset(key, 'verified', 'true');
metadata.contact.verified = true;
Expand Down Expand Up @@ -241,6 +238,10 @@ async function remove({ userId, contact }) {
pipe.del(key);
pipe.srem(redisKey(userId, USERS_CONTACTS), contact.value);

if (this.config.contacts.updateUsername) {
pipe.hdel(USERS_USERNAME_TO_ID, contact.value);
}

return pipe.exec().then(handlePipeline);
}

Expand Down
22 changes: 22 additions & 0 deletions test/suites/actions/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { faker } = require('@faker-js/faker');
const sinon = require('sinon');
const { createMembers } = require('../../helpers/organization');
const { startService, clearRedis } = require('../../config');
const { USERS_USERNAME_TO_ID } = require('../../../src/constants');

describe('#user contacts', function registerSuite() {
const audience = '*.localhost';
Expand Down Expand Up @@ -288,4 +289,25 @@ describe('#user contacts', function registerSuite() {
assert.equal(name, params.metadata.name);
amqpStub.restore();
});

it('should remove username to userid mapping on contact removal', async function test() {
const params = {
username: this.testUser.username,
contact: {
value: 'email@mail.org',
type: 'email',
},
};
await this.users.dispatch('contacts.add', { params });
const amqpStub = sinon.stub(this.users.amqp, 'publish');
amqpStub.withArgs('mailer.predefined').resolves({ queued: true });
await this.users.dispatch('contacts.challenge', { params });
const { ctx: { template: { token: { secret } } } } = amqpStub.args[0][1];
await this.users.dispatch('contacts.verify-email', { params: { secret } });
const userid = await this.users.redis.hget(USERS_USERNAME_TO_ID, params.contact.value);
assert.notEqual(userid, null);
await this.users.dispatch('contacts.remove', { params });
const useridRemoved = await this.users.redis.hget(USERS_USERNAME_TO_ID, params.contact.value);
assert.equal(useridRemoved, null);
});
});
7 changes: 4 additions & 3 deletions test/suites/actions/invite.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ describe('#invite', function registerSuite() {
password: '123',
inviteToken: this.invitationToken,
audience: '*.localhost',
} }), {
name: 'AssertionError',
message: `Sanity check failed for "id" failed: "abnormal@yandex.ru" vs "${email}"`,
} }), (err) => {
assert.strictEqual(err.name, 'AssertionError');
assert.match(err.message, /Sanity check failed for "id" failed: "abnormal@yandex.ru" vs "v@yandex.ru"/);
return true;
});
});

Expand Down