Skip to content

Commit

Permalink
feat: adaptive username (#536)
Browse files Browse the repository at this point in the history
> When executing npm cli owner add command,
[ref](https://github.com/npm/cli/blob/latest/lib/commands/owner.js#L151),
it causes errors due to duplicate additions,when the selfRegistry
configuration has the userPrefix option enabled.
1. 🧶 Modify the user query api to prioritize returning users from
selfRegistry
2. 🧶 Ensure that the query api uniformly returns displayName

---------

> npm cli 执行 owner add 时
[ref](https://github.com/npm/cli/blob/latest/lib/commands/owner.js#L151),依赖查询结果做去重,selfRegistry
配置 userPrefix 时会导致重复添加报错
1. 🧶 修改用户查询接口,优先返回 selfRegistry 内的用户
2. 🧶 查询接口统一返回 displayName
  • Loading branch information
elrrrrrrr committed Jun 28, 2023
1 parent a4a0f2d commit dd69606
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
4 changes: 4 additions & 0 deletions app/common/PackageUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export function cleanUserPrefix(username: string): string {
return username.replace(/^.*:/, '');
}

export function getPrefixedName(prefix: string, username: string): string {
return prefix ? `${prefix}${username}` : username;
}

export async function calculateIntegrity(contentOrFile: Uint8Array | string) {
let integrityObj;
if (typeof contentOrFile === 'string') {
Expand Down
27 changes: 27 additions & 0 deletions app/core/service/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import { WebauthnCredential as WebauthnCredentialEntity } from '../entity/Webaut
import { LoginResultCode } from '../../common/enum/User';
import { integrity, checkIntegrity, randomToken, sha512 } from '../../common/UserUtil';
import { AbstractService } from '../../common/AbstractService';
import { RegistryManagerService } from './RegistryManagerService';
import { getPrefixedName } from '../../common/PackageUtil';
import { Registry } from '../entity/Registry';

type Optional<T, K extends keyof T> = Omit < T, K > & Partial<T> ;

Expand Down Expand Up @@ -59,12 +62,36 @@ type CreateWebauthnCredentialOptions = {
export class UserService extends AbstractService {
@Inject()
private readonly userRepository: UserRepository;
@Inject()
private readonly registryManagerService: RegistryManagerService;

checkPassword(user: UserEntity, password: string): boolean {
const plain = `${user.passwordSalt}${password}`;
return checkIntegrity(plain, user.passwordIntegrity);
}

async findUserByNameOrDisplayName(name: string) {
const hasPrefix = name.includes(':');
if (hasPrefix) {
return await this.findUserByName(name);
}

const selfRegistry = await this.registryManagerService.ensureSelfRegistry();
const selfUser = await this.findUserByName(getPrefixedName(selfRegistry.userPrefix, name));
if (selfUser) {
return selfUser;
}

const defaultRegistry = await this.registryManagerService.ensureDefaultRegistry();
const defaultUser = await this.findUserByName(getPrefixedName(defaultRegistry.userPrefix, name));

return defaultUser;
}

async findInRegistry(registry:Registry, name: string): Promise<UserEntity | null> {
return await this.findUserByName(getPrefixedName(registry.userPrefix, name));
}

async findUserByName(name: string): Promise<UserEntity | null> {
return await this.userRepository.findUserByName(name);
}
Expand Down
12 changes: 6 additions & 6 deletions app/port/controller/UserController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class UserController extends AbstractController {
ctx.status = 201;
return {
ok: true,
id: `org.couchdb.user:${result.user?.name}`,
id: `org.couchdb.user:${result.user?.displayName}`,
rev: result.user?.userId,
token: result.token?.token,
};
Expand All @@ -113,7 +113,7 @@ export class UserController extends AbstractController {
ctx.status = 201;
return {
ok: true,
id: `org.couchdb.user:${userEntity.name}`,
id: `org.couchdb.user:${userEntity.displayName}`,
rev: userEntity.userId,
token: token.token,
};
Expand All @@ -140,14 +140,14 @@ export class UserController extends AbstractController {
method: HTTPMethodEnum.GET,
})
async showUser(@Context() ctx: EggContext, @HTTPParam() username: string) {
const user = await this.userRepository.findUserByName(username);
const user = await this.userService.findUserByNameOrDisplayName(username);
if (!user) {
throw new NotFoundError(`User "${username}" not found`);
}
const authorized = await this.userRoleManager.getAuthorizedUserAndToken(ctx);
return {
_id: `org.couchdb.user:${user.name}`,
name: user.name,
_id: `org.couchdb.user:${user.displayName}`,
name: user.displayName,
email: authorized ? user.email : undefined,
};
}
Expand Down Expand Up @@ -209,7 +209,7 @@ export class UserController extends AbstractController {
// "pending": false,
// "mode": "auth-only"
// },
name: authorizedUser.name,
name: authorizedUser.displayName,
email: authorizedUser.email,
email_verified: false,
created: authorizedUser.createdAt,
Expand Down
25 changes: 25 additions & 0 deletions test/port/controller/UserController/showUser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,31 @@ describe('test/port/controller/UserController/showUser.test.ts', () => {
});
});

it('should clean prefix info', async () => {
const { authorization, email } = await TestUtil.createUser({ name: 'npm:banana' });
const res = await app.httpRequest()
.get(`/-/user/org.couchdb.user:${encodeURIComponent('npm:banana')}`)
.set('authorization', authorization)
.expect(200);
assert.deepEqual(res.body, {
_id: 'org.couchdb.user:banana',
name: 'banana',
email,
});
});

it('should return self user first', async () => {
const { authorization, email } = await TestUtil.createUser({ name: 'npm:apple' });
await TestUtil.createUser({ name: 'apple' });
const res = await app.httpRequest()
.get('/-/user/org.couchdb.user:apple')
.set('authorization', authorization)
.expect(200);

assert.equal(res.body.email, email);
});


it('should 404 when user not exists', async () => {
const { authorization, name } = await TestUtil.createUser();
let res = await app.httpRequest()
Expand Down

0 comments on commit dd69606

Please sign in to comment.