Skip to content

Commit 0070299

Browse files
committed
fix: more flexible user matching
1 parent ae424c1 commit 0070299

File tree

7 files changed

+312
-97
lines changed

7 files changed

+312
-97
lines changed

dist/index.js

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81717,23 +81717,67 @@ var SlackAppUrl;
8171781717
;// CONCATENATED MODULE: ./src/utils/slack/user-matchers.ts
8171881718

8171981719

81720+
/**
81721+
* Redacts sensitive information for safe logging
81722+
* Replaces characters with * but keeps first and last character
81723+
* For emails, obfuscates both username and domain parts
81724+
*/
81725+
function redact(text) {
81726+
if (!text) {
81727+
return '';
81728+
}
81729+
// Handle email addresses specially
81730+
if (text.includes('@')) {
81731+
const [localPart, domainPart] = text.split('@');
81732+
const redactedLocal = redact(localPart);
81733+
// Obfuscate domain part too
81734+
const domainParts = domainPart.split('.');
81735+
const redactedDomain = domainParts.map(part => {
81736+
if (part.length <= 2) {
81737+
return part;
81738+
}
81739+
return `${part[0]}${'*'.repeat(part.length - 2)}${part[part.length - 1]}`;
81740+
}).join('.');
81741+
return `${redactedLocal}@${redactedDomain}`;
81742+
}
81743+
// Handle regular text
81744+
if (text.length <= 2) {
81745+
return text;
81746+
}
81747+
return `${text[0]}${'*'.repeat(text.length - 2)}${text[text.length - 1]}`;
81748+
}
8172081749
function customMappingMatcher(githubUsername, slackUsername) {
8172181750
return {
81722-
check: (user) => user.name?.toLowerCase() === slackUsername.toLowerCase() ||
81723-
user.profile?.display_name?.toLowerCase() === slackUsername.toLowerCase() ||
81724-
user.profile?.real_name?.toLowerCase() === slackUsername.toLowerCase(),
81751+
check: (user) => {
81752+
const name = user.name?.toLowerCase() ?? '';
81753+
const displayName = user.profile?.display_name?.toLowerCase() ?? '';
81754+
const realName = user.profile?.real_name?.toLowerCase() ?? '';
81755+
const slackNameLower = slackUsername.toLowerCase();
81756+
return (name.includes(slackNameLower) ||
81757+
slackNameLower.includes(name) ||
81758+
displayName.includes(slackNameLower) ||
81759+
slackNameLower.includes(displayName) ||
81760+
realName.includes(slackNameLower) ||
81761+
slackNameLower.includes(realName));
81762+
},
8172581763
description: 'custom user mapping',
8172681764
log: (user) => {
8172781765
(0,core.debug)(`Match found by custom mapping: GitHub username [${githubUsername}] to Slack username [${slackUsername}] for user [${user.id}]`);
81766+
(0,core.debug)(`Redacted debug info: GitHub username [${redact(githubUsername)}] to Slack username [${redact(slackUsername)}] matched with user name [${redact(user.name ?? '')}], display_name [${redact(user.profile?.display_name ?? '')}], real_name [${redact(user.profile?.real_name ?? '')}]`);
8172881767
},
8172981768
};
8173081769
}
8173181770
function displayNameMatcher(username) {
8173281771
return {
81733-
check: (user) => user.profile?.display_name?.toLowerCase() === username.toLowerCase(),
81772+
check: (user) => {
81773+
const displayName = user.profile?.display_name?.toLowerCase() ?? '';
81774+
const usernameLower = username.toLowerCase();
81775+
return displayName.includes(usernameLower) || usernameLower.includes(displayName);
81776+
},
8173481777
description: 'user.profile.display_name fields',
8173581778
log: (user) => {
8173681779
(0,core.debug)(`Match found by username [${username}] matching Slack displayName [${user.profile?.display_name}]`);
81780+
(0,core.debug)(`Redacted debug info: username [${redact(username)}] matched with display_name [${redact(user.profile?.display_name ?? '')}]`);
8173781781
},
8173881782
};
8173981783
}
@@ -81745,6 +81789,7 @@ function emailContainsMatcher(username) {
8174581789
description: 'user.profile.email contains check',
8174681790
log: (user) => {
8174781791
(0,core.debug)(`Match found by username [${username}] contained in Slack email [${user.profile?.email}]`);
81792+
(0,core.debug)(`Redacted debug info: username [${redact(username)}] matched with email [${redact(user.profile?.email ?? '')}]`);
8174881793
},
8174981794
};
8175081795
}
@@ -81754,15 +81799,21 @@ function emailMatcher(email) {
8175481799
description: 'user.profile.email fields',
8175581800
log: (user) => {
8175681801
(0,core.debug)(`Match found by email [${email}] with Slack email [${user.profile?.email}]`);
81802+
(0,core.debug)(`Redacted debug info: email [${redact(email)}] matched with Slack email [${redact(user.profile?.email ?? '')}]`);
8175781803
},
8175881804
};
8175981805
}
8176081806
function realNameMatcher(username) {
8176181807
return {
81762-
check: (user) => user.profile?.real_name?.toLowerCase() === username.toLowerCase(),
81808+
check: (user) => {
81809+
const realName = user.profile?.real_name?.toLowerCase() ?? '';
81810+
const usernameLower = username.toLowerCase();
81811+
return realName.includes(usernameLower) || usernameLower.includes(realName);
81812+
},
8176381813
description: 'user.profile.real_name fields',
8176481814
log: (user) => {
8176581815
(0,core.debug)(`Match found by username [${username}] matching Slack realName [${user.profile?.real_name}]`);
81816+
(0,core.debug)(`Redacted debug info: username [${redact(username)}] matched with real_name [${redact(user.profile?.real_name ?? '')}]`);
8176681817
},
8176781818
};
8176881819
}
@@ -81772,6 +81823,7 @@ function userIdMatcher(userId) {
8177281823
description: 'user.id fields',
8177381824
log: (user) => {
8177481825
(0,core.debug)(`Match found by userId [${userId}] with Slack userId [${user.id}]`);
81826+
(0,core.debug)(`Redacted debug info: userId matched with Slack userId [${redact(user.id ?? '')}]`);
8177581827
},
8177681828
};
8177781829
}
@@ -81782,6 +81834,7 @@ const createUserMatchers = ({ email, userId, userMappings = [], username }) => {
8178281834
const matchingMappings = userMappings.filter((mapping) => mapping.githubUsername === username);
8178381835
if (matchingMappings.length > 0) {
8178481836
(0,core.debug)(`Found [${matchingMappings.length}] custom mappings for GitHub username [${username}]`);
81837+
(0,core.debug)(`Redacted debug info: Found [${matchingMappings.length}] custom mappings for GitHub username [${redact(username)}]`);
8178581838
// Add a matcher for each mapping
8178681839
matchingMappings.forEach((mapping) => {
8178781840
matchers.push(customMappingMatcher(username, mapping.slackUsername));
@@ -81804,25 +81857,35 @@ const createUserMatchers = ({ email, userId, userMappings = [], username }) => {
8180481857
};
8180581858
const logFailedMatches = ({ email, userId, userMappings = [], username }, usersCount) => {
8180681859
console.log(`No user match found for [${username}] after checking against [${usersCount}] Slack ${(0,src.plural)('user', usersCount)}`);
81860+
// Redacted version
81861+
console.log(`Redacted debug info: No user match found for [${redact(username ?? '')}] after checking against [${usersCount}] Slack ${(0,src.plural)('user', usersCount)}`);
8180781862
// Log mapping failures
8180881863
if (username && userMappings.length > 0) {
8180981864
const matchingMappings = userMappings.filter((mapping) => mapping.githubUsername === username);
8181081865
if (matchingMappings.length > 0) {
8181181866
(0,core.debug)(`WARNING: Custom mappings for GitHub username [${username}] were defined but no matching Slack users were found:`);
81867+
(0,core.debug)(`Redacted debug info: WARNING: Custom mappings for GitHub username [${redact(username)}] were defined but no matching Slack users were found:`);
8181281868
// Show each mapping that failed
8181381869
matchingMappings.forEach((mapping) => {
8181481870
(0,core.debug)(` - Mapped to Slack username [${mapping.slackUsername}] but no Slack user with this name/display_name/real_name was found`);
81871+
(0,core.debug)(` - Redacted debug info: Mapped to Slack username [${redact(mapping.slackUsername)}] but no Slack user with this name/display_name/real_name was found`);
8181581872
});
8181681873
(0,core.debug)(`Attempted to fall back to standard matching methods`);
8181781874
}
8181881875
}
8181981876
// Log standard matchers that were tried
81820-
if (userId)
81877+
if (userId) {
8182181878
(0,core.debug)(`Tried to match userId [${userId}] against Slack user.id fields`);
81822-
if (email)
81879+
(0,core.debug)(`Redacted debug info: Tried to match userId [${redact(userId)}] against Slack user.id fields`);
81880+
}
81881+
if (email) {
8182381882
(0,core.debug)(`Tried to match email [${email}] against Slack user.profile.email fields`);
81824-
if (username)
81883+
(0,core.debug)(`Redacted debug info: Tried to match email [${redact(email)}] against Slack user.profile.email fields`);
81884+
}
81885+
if (username) {
8182581886
(0,core.debug)(`Tried to match username [${username}] against Slack user.profile.email (contains), display_name and real_name fields`);
81887+
(0,core.debug)(`Redacted debug info: Tried to match username [${redact(username)}] against Slack user.profile.email (contains), display_name and real_name fields`);
81888+
}
8182681889
(0,core.debug)(`Since no Slack user match found, unable to @mention user or use their profile image`);
8182781890
};
8182881891

@@ -90631,7 +90694,7 @@ module.exports = {"version":"3.17.0"};
9063190694
/***/ 8330:
9063290695
/***/ ((module) => {
9063390696

90634-
module.exports = /*#__PURE__*/JSON.parse('{"UU":"@krauters/github-notifier","rE":"1.3.2","TB":"https://buymeacoffee.com/coltenkrauter"}');
90697+
module.exports = /*#__PURE__*/JSON.parse('{"UU":"@krauters/github-notifier","rE":"1.3.3","TB":"https://buymeacoffee.com/coltenkrauter"}');
9063590698

9063690699
/***/ })
9063790700

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@krauters/github-notifier",
33
"description": "GitHub Notifier by Krauters – Post Open Pull Requests to Slack",
4-
"version": "1.3.2",
4+
"version": "1.3.3",
55
"author": "Colten Krauter <coltenkrauter>",
66
"type": "module",
77
"homepage": "https://buymeacoffee.com/coltenkrauter",

src/utils/slack/user-matchers.ts

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,87 @@ export interface UserMatcher {
1717
log: (user: Member) => void
1818
}
1919

20+
/**
21+
* Redacts sensitive information for safe logging
22+
* Replaces characters with * but keeps first and last character
23+
* For emails, obfuscates both username and domain parts
24+
*/
25+
export function redact(text: string): string {
26+
if (!text) {
27+
return ''
28+
}
29+
30+
// Handle email addresses specially
31+
if (text.includes('@')) {
32+
const [localPart, domainPart] = text.split('@')
33+
const redactedLocal = redact(localPart)
34+
35+
// Obfuscate domain part too
36+
const domainParts = domainPart.split('.')
37+
const redactedDomain = domainParts
38+
.map((part) => {
39+
if (part.length <= 2) {
40+
return part
41+
}
42+
43+
return `${part[0]}${'*'.repeat(part.length - 2)}${part[part.length - 1]}`
44+
})
45+
.join('.')
46+
47+
return `${redactedLocal}@${redactedDomain}`
48+
}
49+
50+
// Handle regular text
51+
if (text.length <= 2) {
52+
return text
53+
}
54+
55+
return `${text[0]}${'*'.repeat(text.length - 2)}${text[text.length - 1]}`
56+
}
57+
2058
function customMappingMatcher(githubUsername: string, slackUsername: string): UserMatcher {
2159
return {
22-
check: (user: Member) =>
23-
user.name?.toLowerCase() === slackUsername.toLowerCase() ||
24-
user.profile?.display_name?.toLowerCase() === slackUsername.toLowerCase() ||
25-
user.profile?.real_name?.toLowerCase() === slackUsername.toLowerCase(),
60+
check: (user: Member) => {
61+
const name = user.name?.toLowerCase() ?? ''
62+
const displayName = user.profile?.display_name?.toLowerCase() ?? ''
63+
const realName = user.profile?.real_name?.toLowerCase() ?? ''
64+
const slackNameLower = slackUsername.toLowerCase()
65+
66+
return (
67+
name.includes(slackNameLower) ||
68+
slackNameLower.includes(name) ||
69+
displayName.includes(slackNameLower) ||
70+
slackNameLower.includes(displayName) ||
71+
realName.includes(slackNameLower) ||
72+
slackNameLower.includes(realName)
73+
)
74+
},
2675
description: 'custom user mapping',
2776
log: (user: Member) => {
2877
debug(
2978
`Match found by custom mapping: GitHub username [${githubUsername}] to Slack username [${slackUsername}] for user [${user.id}]`,
3079
)
80+
debug(
81+
`Redacted debug info: GitHub username [${redact(githubUsername)}] to Slack username [${redact(slackUsername)}] matched with user name [${redact(user.name ?? '')}], display_name [${redact(user.profile?.display_name ?? '')}], real_name [${redact(user.profile?.real_name ?? '')}]`,
82+
)
3183
},
3284
}
3385
}
3486

3587
function displayNameMatcher(username: string): UserMatcher {
3688
return {
37-
check: (user: Member) => user.profile?.display_name?.toLowerCase() === username.toLowerCase(),
89+
check: (user: Member) => {
90+
const displayName = user.profile?.display_name?.toLowerCase() ?? ''
91+
const usernameLower = username.toLowerCase()
92+
93+
return displayName.includes(usernameLower) || usernameLower.includes(displayName)
94+
},
3895
description: 'user.profile.display_name fields',
3996
log: (user: Member) => {
4097
debug(`Match found by username [${username}] matching Slack displayName [${user.profile?.display_name}]`)
98+
debug(
99+
`Redacted debug info: username [${redact(username)}] matched with display_name [${redact(user.profile?.display_name ?? '')}]`,
100+
)
41101
},
42102
}
43103
}
@@ -51,6 +111,9 @@ function emailContainsMatcher(username: string): UserMatcher {
51111
description: 'user.profile.email contains check',
52112
log: (user: Member) => {
53113
debug(`Match found by username [${username}] contained in Slack email [${user.profile?.email}]`)
114+
debug(
115+
`Redacted debug info: username [${redact(username)}] matched with email [${redact(user.profile?.email ?? '')}]`,
116+
)
54117
},
55118
}
56119
}
@@ -61,16 +124,27 @@ function emailMatcher(email: string): UserMatcher {
61124
description: 'user.profile.email fields',
62125
log: (user: Member) => {
63126
debug(`Match found by email [${email}] with Slack email [${user.profile?.email}]`)
127+
debug(
128+
`Redacted debug info: email [${redact(email)}] matched with Slack email [${redact(user.profile?.email ?? '')}]`,
129+
)
64130
},
65131
}
66132
}
67133

68134
function realNameMatcher(username: string): UserMatcher {
69135
return {
70-
check: (user: Member) => user.profile?.real_name?.toLowerCase() === username.toLowerCase(),
136+
check: (user: Member) => {
137+
const realName = user.profile?.real_name?.toLowerCase() ?? ''
138+
const usernameLower = username.toLowerCase()
139+
140+
return realName.includes(usernameLower) || usernameLower.includes(realName)
141+
},
71142
description: 'user.profile.real_name fields',
72143
log: (user: Member) => {
73144
debug(`Match found by username [${username}] matching Slack realName [${user.profile?.real_name}]`)
145+
debug(
146+
`Redacted debug info: username [${redact(username)}] matched with real_name [${redact(user.profile?.real_name ?? '')}]`,
147+
)
74148
},
75149
}
76150
}
@@ -81,6 +155,7 @@ function userIdMatcher(userId: string): UserMatcher {
81155
description: 'user.id fields',
82156
log: (user: Member) => {
83157
debug(`Match found by userId [${userId}] with Slack userId [${user.id}]`)
158+
debug(`Redacted debug info: userId matched with Slack userId [${redact(user.id ?? '')}]`)
84159
},
85160
}
86161
}
@@ -94,6 +169,9 @@ export const createUserMatchers = ({ email, userId, userMappings = [], username
94169

95170
if (matchingMappings.length > 0) {
96171
debug(`Found [${matchingMappings.length}] custom mappings for GitHub username [${username}]`)
172+
debug(
173+
`Redacted debug info: Found [${matchingMappings.length}] custom mappings for GitHub username [${redact(username)}]`,
174+
)
97175

98176
// Add a matcher for each mapping
99177
matchingMappings.forEach((mapping) => {
@@ -128,6 +206,11 @@ export const logFailedMatches = (
128206
`No user match found for [${username}] after checking against [${usersCount}] Slack ${plural('user', usersCount)}`,
129207
)
130208

209+
// Redacted version
210+
console.log(
211+
`Redacted debug info: No user match found for [${redact(username ?? '')}] after checking against [${usersCount}] Slack ${plural('user', usersCount)}`,
212+
)
213+
131214
// Log mapping failures
132215
if (username && userMappings.length > 0) {
133216
const matchingMappings = userMappings.filter((mapping) => mapping.githubUsername === username)
@@ -136,24 +219,43 @@ export const logFailedMatches = (
136219
`WARNING: Custom mappings for GitHub username [${username}] were defined but no matching Slack users were found:`,
137220
)
138221

222+
debug(
223+
`Redacted debug info: WARNING: Custom mappings for GitHub username [${redact(username)}] were defined but no matching Slack users were found:`,
224+
)
225+
139226
// Show each mapping that failed
140227
matchingMappings.forEach((mapping) => {
141228
debug(
142229
` - Mapped to Slack username [${mapping.slackUsername}] but no Slack user with this name/display_name/real_name was found`,
143230
)
231+
debug(
232+
` - Redacted debug info: Mapped to Slack username [${redact(mapping.slackUsername)}] but no Slack user with this name/display_name/real_name was found`,
233+
)
144234
})
145235

146236
debug(`Attempted to fall back to standard matching methods`)
147237
}
148238
}
149239

150240
// Log standard matchers that were tried
151-
if (userId) debug(`Tried to match userId [${userId}] against Slack user.id fields`)
152-
if (email) debug(`Tried to match email [${email}] against Slack user.profile.email fields`)
153-
if (username)
241+
if (userId) {
242+
debug(`Tried to match userId [${userId}] against Slack user.id fields`)
243+
debug(`Redacted debug info: Tried to match userId [${redact(userId)}] against Slack user.id fields`)
244+
}
245+
246+
if (email) {
247+
debug(`Tried to match email [${email}] against Slack user.profile.email fields`)
248+
debug(`Redacted debug info: Tried to match email [${redact(email)}] against Slack user.profile.email fields`)
249+
}
250+
251+
if (username) {
154252
debug(
155253
`Tried to match username [${username}] against Slack user.profile.email (contains), display_name and real_name fields`,
156254
)
255+
debug(
256+
`Redacted debug info: Tried to match username [${redact(username)}] against Slack user.profile.email (contains), display_name and real_name fields`,
257+
)
258+
}
157259

158260
debug(`Since no Slack user match found, unable to @mention user or use their profile image`)
159261
}

0 commit comments

Comments
 (0)