mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-22 17:56:30 -05:00
fix username spelling from userName
Signed-off-by: Yannick Bungers <git@innay.de>
This commit is contained in:
parent
aa8455a079
commit
d33cfa4541
23 changed files with 89 additions and 91 deletions
|
@ -50,9 +50,9 @@ export class MeController {
|
||||||
for (const mediaUpload of mediaUploads) {
|
for (const mediaUpload of mediaUploads) {
|
||||||
await this.mediaService.deleteFile(mediaUpload);
|
await this.mediaService.deleteFile(mediaUpload);
|
||||||
}
|
}
|
||||||
this.logger.debug(`Deleted all media uploads of ${user.userName}`);
|
this.logger.debug(`Deleted all media uploads of ${user.username}`);
|
||||||
await this.userService.deleteUser(user);
|
await this.userService.deleteUser(user);
|
||||||
this.logger.debug(`Deleted ${user.userName}`);
|
this.logger.debug(`Deleted ${user.username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('profile')
|
@Post('profile')
|
||||||
|
|
|
@ -56,7 +56,7 @@ export class MediaController {
|
||||||
// TODO: Move getting the Note object into a decorator
|
// TODO: Move getting the Note object into a decorator
|
||||||
const note: Note = await this.noteService.getNoteByIdOrAlias(noteId);
|
const note: Note = await this.noteService.getNoteByIdOrAlias(noteId);
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.userName}'`,
|
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.username}'`,
|
||||||
'uploadMedia',
|
'uploadMedia',
|
||||||
);
|
);
|
||||||
const url = await this.mediaService.saveFile(file.buffer, user, note);
|
const url = await this.mediaService.saveFile(file.buffer, user, note);
|
||||||
|
|
|
@ -52,7 +52,7 @@ export class TokensController {
|
||||||
@RequestUser() user: User,
|
@RequestUser() user: User,
|
||||||
): Promise<AuthTokenWithSecretDto> {
|
): Promise<AuthTokenWithSecretDto> {
|
||||||
return await this.authService.createTokenForUser(
|
return await this.authService.createTokenForUser(
|
||||||
user.userName,
|
user.username,
|
||||||
label,
|
label,
|
||||||
validUntil,
|
validUntil,
|
||||||
);
|
);
|
||||||
|
|
|
@ -100,7 +100,7 @@ export class MediaController {
|
||||||
// TODO: Move getting the Note object into a decorator
|
// TODO: Move getting the Note object into a decorator
|
||||||
const note: Note = await this.noteService.getNoteByIdOrAlias(noteId);
|
const note: Note = await this.noteService.getNoteByIdOrAlias(noteId);
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.userName}'`,
|
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.username}'`,
|
||||||
'uploadMedia',
|
'uploadMedia',
|
||||||
);
|
);
|
||||||
const url = await this.mediaService.saveFile(file.buffer, user, note);
|
const url = await this.mediaService.saveFile(file.buffer, user, note);
|
||||||
|
@ -127,7 +127,7 @@ export class MediaController {
|
||||||
@RequestUser() user: User,
|
@RequestUser() user: User,
|
||||||
@Param('filename') filename: string,
|
@Param('filename') filename: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const username = user.userName;
|
const username = user.username;
|
||||||
try {
|
try {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Deleting '${filename}' for user '${username}'`,
|
`Deleting '${filename}' for user '${username}'`,
|
||||||
|
@ -136,7 +136,7 @@ export class MediaController {
|
||||||
const mediaUpload = await this.mediaService.findUploadByFilename(
|
const mediaUpload = await this.mediaService.findUploadByFilename(
|
||||||
filename,
|
filename,
|
||||||
);
|
);
|
||||||
if (mediaUpload.user.userName !== username) {
|
if (mediaUpload.user.username !== username) {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
`${username} tried to delete '${filename}', but is not the owner`,
|
`${username} tried to delete '${filename}', but is not the owner`,
|
||||||
'deleteMedia',
|
'deleteMedia',
|
||||||
|
|
|
@ -242,7 +242,7 @@ describe('AuthService', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const token = await service.createTokenForUser(
|
const token = await service.createTokenForUser(
|
||||||
user.userName,
|
user.username,
|
||||||
identifier,
|
identifier,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
@ -269,7 +269,7 @@ describe('AuthService', () => {
|
||||||
);
|
);
|
||||||
const validUntil = new Date().getTime() + 30000;
|
const validUntil = new Date().getTime() + 30000;
|
||||||
const token = await service.createTokenForUser(
|
const token = await service.createTokenForUser(
|
||||||
user.userName,
|
user.username,
|
||||||
identifier,
|
identifier,
|
||||||
validUntil,
|
validUntil,
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,22 +54,22 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
const accessToken = await this.getAuthTokenAndValidate(keyId, secret);
|
const accessToken = await this.getAuthTokenAndValidate(keyId, secret);
|
||||||
await this.setLastUsedToken(keyId);
|
await this.setLastUsedToken(keyId);
|
||||||
return await this.usersService.getUserByUsername(accessToken.user.userName);
|
return await this.usersService.getUserByUsername(accessToken.user.username);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createTokenForUser(
|
async createTokenForUser(
|
||||||
userName: string,
|
username: string,
|
||||||
identifier: string,
|
identifier: string,
|
||||||
validUntil: TimestampMillis,
|
validUntil: TimestampMillis,
|
||||||
): Promise<AuthTokenWithSecretDto> {
|
): Promise<AuthTokenWithSecretDto> {
|
||||||
const user = await this.usersService.getUserByUsername(userName, [
|
const user = await this.usersService.getUserByUsername(username, [
|
||||||
UserRelationEnum.AUTHTOKENS,
|
UserRelationEnum.AUTHTOKENS,
|
||||||
]);
|
]);
|
||||||
if (user.authTokens.length >= 200) {
|
if (user.authTokens.length >= 200) {
|
||||||
// This is a very high ceiling unlikely to hinder legitimate usage,
|
// This is a very high ceiling unlikely to hinder legitimate usage,
|
||||||
// but should prevent possible attack vectors
|
// but should prevent possible attack vectors
|
||||||
throw new TooManyTokensError(
|
throw new TooManyTokensError(
|
||||||
`User '${user.userName}' has already 200 tokens and can't have anymore`,
|
`User '${user.username}' has already 200 tokens and can't have anymore`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const secret = bufferToBase64Url(randomBytes(54));
|
const secret = bufferToBase64Url(randomBytes(54));
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { NotInDBError } from '../errors/errors';
|
||||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { NotesService } from '../notes/notes.service';
|
import { NotesService } from '../notes/notes.service';
|
||||||
import { getPrimaryAlias } from '../notes/utils';
|
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersService } from '../users/users.service';
|
import { UsersService } from '../users/users.service';
|
||||||
import { HistoryEntryImportDto } from './history-entry-import.dto';
|
import { HistoryEntryImportDto } from './history-entry-import.dto';
|
||||||
|
@ -64,7 +63,7 @@ export class HistoryService {
|
||||||
});
|
});
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
throw new NotInDBError(
|
throw new NotInDBError(
|
||||||
`User '${user.userName}' has no HistoryEntry for Note with id '${note.id}'`,
|
`User '${user.username}' has no HistoryEntry for Note with id '${note.id}'`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class IdentityService {
|
||||||
await getFirstIdentityFromUser(user, ProviderType.LOCAL);
|
await getFirstIdentityFromUser(user, ProviderType.LOCAL);
|
||||||
if (internalIdentity === undefined) {
|
if (internalIdentity === undefined) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`The user with the username ${user.userName} does not have a internal identity.`,
|
`The user with the username ${user.username} does not have a internal identity.`,
|
||||||
'updateLocalPassword',
|
'updateLocalPassword',
|
||||||
);
|
);
|
||||||
throw new NotInDBError('This user has no internal identity.');
|
throw new NotInDBError('This user has no internal identity.');
|
||||||
|
@ -78,14 +78,14 @@ export class IdentityService {
|
||||||
await getFirstIdentityFromUser(user, ProviderType.LOCAL);
|
await getFirstIdentityFromUser(user, ProviderType.LOCAL);
|
||||||
if (internalIdentity === undefined) {
|
if (internalIdentity === undefined) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`The user with the username ${user.userName} does not have a internal identity.`,
|
`The user with the username ${user.username} does not have a internal identity.`,
|
||||||
'loginWithLocalIdentity',
|
'loginWithLocalIdentity',
|
||||||
);
|
);
|
||||||
throw new NotInDBError();
|
throw new NotInDBError();
|
||||||
}
|
}
|
||||||
if (!(await checkPassword(password, internalIdentity.passwordHash ?? ''))) {
|
if (!(await checkPassword(password, internalIdentity.passwordHash ?? ''))) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Password check for ${user.userName} did not succeed.`,
|
`Password check for ${user.username} did not succeed.`,
|
||||||
'loginWithLocalIdentity',
|
'loginWithLocalIdentity',
|
||||||
);
|
);
|
||||||
throw new NotInDBError();
|
throw new NotInDBError();
|
||||||
|
|
|
@ -33,10 +33,10 @@ export class MediaUploadDto {
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The userName of the user which uploaded the media file.
|
* The username of the user which uploaded the media file.
|
||||||
* @example "testuser5"
|
* @example "testuser5"
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
userName: string;
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ describe('MediaService', () => {
|
||||||
id: 'testMediaUpload',
|
id: 'testMediaUpload',
|
||||||
backendData: 'testBackendData',
|
backendData: 'testBackendData',
|
||||||
user: {
|
user: {
|
||||||
userName: 'hardcoded',
|
username: 'hardcoded',
|
||||||
} as User,
|
} as User,
|
||||||
} as MediaUpload;
|
} as MediaUpload;
|
||||||
jest
|
jest
|
||||||
|
@ -191,20 +191,20 @@ describe('MediaService', () => {
|
||||||
describe('findUploadByFilename', () => {
|
describe('findUploadByFilename', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const testFileName = 'testFilename';
|
const testFileName = 'testFilename';
|
||||||
const userName = 'hardcoded';
|
const username = 'hardcoded';
|
||||||
const backendData = 'testBackendData';
|
const backendData = 'testBackendData';
|
||||||
const mockMediaUploadEntry = {
|
const mockMediaUploadEntry = {
|
||||||
id: 'testMediaUpload',
|
id: 'testMediaUpload',
|
||||||
backendData: backendData,
|
backendData: backendData,
|
||||||
user: {
|
user: {
|
||||||
userName: userName,
|
username: username,
|
||||||
} as User,
|
} as User,
|
||||||
} as MediaUpload;
|
} as MediaUpload;
|
||||||
jest
|
jest
|
||||||
.spyOn(mediaRepo, 'findOne')
|
.spyOn(mediaRepo, 'findOne')
|
||||||
.mockResolvedValueOnce(mockMediaUploadEntry);
|
.mockResolvedValueOnce(mockMediaUploadEntry);
|
||||||
const mediaUpload = await service.findUploadByFilename(testFileName);
|
const mediaUpload = await service.findUploadByFilename(testFileName);
|
||||||
expect(mediaUpload.user.userName).toEqual(userName);
|
expect(mediaUpload.user.username).toEqual(username);
|
||||||
expect(mediaUpload.backendData).toEqual(backendData);
|
expect(mediaUpload.backendData).toEqual(backendData);
|
||||||
});
|
});
|
||||||
it("fails: can't find mediaUpload", async () => {
|
it("fails: can't find mediaUpload", async () => {
|
||||||
|
@ -223,28 +223,28 @@ describe('MediaService', () => {
|
||||||
id: 'testMediaUpload',
|
id: 'testMediaUpload',
|
||||||
backendData: 'testBackendData',
|
backendData: 'testBackendData',
|
||||||
user: {
|
user: {
|
||||||
userName: 'hardcoded',
|
username: 'hardcoded',
|
||||||
} as User,
|
} as User,
|
||||||
} as MediaUpload;
|
} as MediaUpload;
|
||||||
jest
|
jest
|
||||||
.spyOn(mediaRepo, 'find')
|
.spyOn(mediaRepo, 'find')
|
||||||
.mockResolvedValueOnce([mockMediaUploadEntry]);
|
.mockResolvedValueOnce([mockMediaUploadEntry]);
|
||||||
expect(
|
expect(
|
||||||
await service.listUploadsByUser({ userName: 'hardcoded' } as User),
|
await service.listUploadsByUser({ username: 'hardcoded' } as User),
|
||||||
).toEqual([mockMediaUploadEntry]);
|
).toEqual([mockMediaUploadEntry]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('without uploads from user', async () => {
|
it('without uploads from user', async () => {
|
||||||
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce([]);
|
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce([]);
|
||||||
const mediaList = await service.listUploadsByUser({
|
const mediaList = await service.listUploadsByUser({
|
||||||
userName: 'hardcoded',
|
username: 'hardcoded',
|
||||||
} as User);
|
} as User);
|
||||||
expect(mediaList).toEqual([]);
|
expect(mediaList).toEqual([]);
|
||||||
});
|
});
|
||||||
it('with error (undefined as return value of find)', async () => {
|
it('with error (undefined as return value of find)', async () => {
|
||||||
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce(undefined);
|
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce(undefined);
|
||||||
const mediaList = await service.listUploadsByUser({
|
const mediaList = await service.listUploadsByUser({
|
||||||
userName: 'hardcoded',
|
username: 'hardcoded',
|
||||||
} as User);
|
} as User);
|
||||||
expect(mediaList).toEqual([]);
|
expect(mediaList).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -278,7 +278,7 @@ describe('MediaService', () => {
|
||||||
expect(mediaList).toEqual([]);
|
expect(mediaList).toEqual([]);
|
||||||
});
|
});
|
||||||
it('with error (undefined as return value of find)', async () => {
|
it('with error (undefined as return value of find)', async () => {
|
||||||
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce(undefined);
|
jest.spyOn(mediaRepo, 'find').mockResolvedValueOnce([]);
|
||||||
const mediaList = await service.listUploadsByNote({
|
const mediaList = await service.listUploadsByNote({
|
||||||
id: '123',
|
id: '123',
|
||||||
} as Note);
|
} as Note);
|
||||||
|
@ -296,7 +296,7 @@ describe('MediaService', () => {
|
||||||
aliases: [Alias.create('test', true)],
|
aliases: [Alias.create('test', true)],
|
||||||
} as Note,
|
} as Note,
|
||||||
user: {
|
user: {
|
||||||
userName: 'hardcoded',
|
username: 'hardcoded',
|
||||||
} as User,
|
} as User,
|
||||||
} as MediaUpload;
|
} as MediaUpload;
|
||||||
jest
|
jest
|
||||||
|
|
|
@ -78,7 +78,7 @@ export class MediaService {
|
||||||
*/
|
*/
|
||||||
async saveFile(fileBuffer: Buffer, user: User, note: Note): Promise<string> {
|
async saveFile(fileBuffer: Buffer, user: User, note: Note): Promise<string> {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Saving file for note '${note.id}' and user '${user.userName}'`,
|
`Saving file for note '${note.id}' and user '${user.username}'`,
|
||||||
'saveFile',
|
'saveFile',
|
||||||
);
|
);
|
||||||
const fileTypeResult = await FileType.fromBuffer(fileBuffer);
|
const fileTypeResult = await FileType.fromBuffer(fileBuffer);
|
||||||
|
@ -223,7 +223,7 @@ export class MediaService {
|
||||||
url: mediaUpload.fileUrl,
|
url: mediaUpload.fileUrl,
|
||||||
noteId: mediaUpload.note?.id ?? null,
|
noteId: mediaUpload.note?.id ?? null,
|
||||||
createdAt: mediaUpload.createdAt,
|
createdAt: mediaUpload.createdAt,
|
||||||
userName: mediaUpload.user.userName,
|
username: mediaUpload.user.username,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ export class NoteMetadataDto {
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
editedBy: UserInfoDto['userName'][];
|
editedBy: UserInfoDto['username'][];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permissions currently in effect for the note
|
* Permissions currently in effect for the note
|
||||||
|
|
|
@ -266,7 +266,7 @@ describe('NotesService', () => {
|
||||||
describe('getFirstRevision', () => {
|
describe('getFirstRevision', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const user = {} as User;
|
const user = {} as User;
|
||||||
user.userName = 'hardcoded';
|
user.username = 'hardcoded';
|
||||||
const content = 'testContent';
|
const content = 'testContent';
|
||||||
jest
|
jest
|
||||||
.spyOn(noteRepo, 'save')
|
.spyOn(noteRepo, 'save')
|
||||||
|
@ -393,7 +393,7 @@ describe('NotesService', () => {
|
||||||
sharedToGroups: [],
|
sharedToGroups: [],
|
||||||
});
|
});
|
||||||
expect(savedNote.userPermissions).toHaveLength(1);
|
expect(savedNote.userPermissions).toHaveLength(1);
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -421,7 +421,7 @@ describe('NotesService', () => {
|
||||||
sharedToGroups: [],
|
sharedToGroups: [],
|
||||||
});
|
});
|
||||||
expect(savedNote.userPermissions).toHaveLength(1);
|
expect(savedNote.userPermissions).toHaveLength(1);
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -460,7 +460,7 @@ describe('NotesService', () => {
|
||||||
sharedToUsers: [userPermissionUpdate],
|
sharedToUsers: [userPermissionUpdate],
|
||||||
sharedToGroups: [groupPermissionUpate],
|
sharedToGroups: [groupPermissionUpate],
|
||||||
});
|
});
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -496,7 +496,7 @@ describe('NotesService', () => {
|
||||||
sharedToGroups: [groupPermissionUpate],
|
sharedToGroups: [groupPermissionUpate],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -562,7 +562,7 @@ describe('NotesService', () => {
|
||||||
sharedToGroups: [groupPermissionUpate],
|
sharedToGroups: [groupPermissionUpate],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -605,7 +605,7 @@ describe('NotesService', () => {
|
||||||
sharedToGroups: [groupPermissionUpate],
|
sharedToGroups: [groupPermissionUpate],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].user.userName).toEqual(
|
expect(savedNote.userPermissions[0].user.username).toEqual(
|
||||||
userPermissionUpdate.username,
|
userPermissionUpdate.username,
|
||||||
);
|
);
|
||||||
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
expect(savedNote.userPermissions[0].canEdit).toEqual(
|
||||||
|
@ -685,9 +685,9 @@ describe('NotesService', () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const permissions = service.toNotePermissionsDto(note);
|
const permissions = service.toNotePermissionsDto(note);
|
||||||
expect(permissions.owner.userName).toEqual(user.userName);
|
expect(permissions.owner.username).toEqual(user.username);
|
||||||
expect(permissions.sharedToUsers).toHaveLength(1);
|
expect(permissions.sharedToUsers).toHaveLength(1);
|
||||||
expect(permissions.sharedToUsers[0].user.userName).toEqual(user.userName);
|
expect(permissions.sharedToUsers[0].user.username).toEqual(user.username);
|
||||||
expect(permissions.sharedToUsers[0].canEdit).toEqual(true);
|
expect(permissions.sharedToUsers[0].canEdit).toEqual(true);
|
||||||
expect(permissions.sharedToGroups).toHaveLength(1);
|
expect(permissions.sharedToGroups).toHaveLength(1);
|
||||||
expect(permissions.sharedToGroups[0].group.displayName).toEqual(
|
expect(permissions.sharedToGroups[0].group.displayName).toEqual(
|
||||||
|
@ -772,11 +772,11 @@ describe('NotesService', () => {
|
||||||
expect(metadataDto.createTime).toEqual(revisions[0].createdAt);
|
expect(metadataDto.createTime).toEqual(revisions[0].createdAt);
|
||||||
expect(metadataDto.description).toEqual(note.description);
|
expect(metadataDto.description).toEqual(note.description);
|
||||||
expect(metadataDto.editedBy).toHaveLength(1);
|
expect(metadataDto.editedBy).toHaveLength(1);
|
||||||
expect(metadataDto.editedBy[0]).toEqual(user.userName);
|
expect(metadataDto.editedBy[0]).toEqual(user.username);
|
||||||
expect(metadataDto.permissions.owner.userName).toEqual(user.userName);
|
expect(metadataDto.permissions.owner.username).toEqual(user.username);
|
||||||
expect(metadataDto.permissions.sharedToUsers).toHaveLength(1);
|
expect(metadataDto.permissions.sharedToUsers).toHaveLength(1);
|
||||||
expect(metadataDto.permissions.sharedToUsers[0].user.userName).toEqual(
|
expect(metadataDto.permissions.sharedToUsers[0].user.username).toEqual(
|
||||||
user.userName,
|
user.username,
|
||||||
);
|
);
|
||||||
expect(metadataDto.permissions.sharedToUsers[0].canEdit).toEqual(true);
|
expect(metadataDto.permissions.sharedToUsers[0].canEdit).toEqual(true);
|
||||||
expect(metadataDto.permissions.sharedToGroups).toHaveLength(1);
|
expect(metadataDto.permissions.sharedToGroups).toHaveLength(1);
|
||||||
|
@ -787,7 +787,7 @@ describe('NotesService', () => {
|
||||||
expect(metadataDto.tags).toHaveLength(1);
|
expect(metadataDto.tags).toHaveLength(1);
|
||||||
expect(metadataDto.tags[0]).toEqual(note.tags[0].name);
|
expect(metadataDto.tags[0]).toEqual(note.tags[0].name);
|
||||||
expect(metadataDto.updateTime).toEqual(revisions[0].createdAt);
|
expect(metadataDto.updateTime).toEqual(revisions[0].createdAt);
|
||||||
expect(metadataDto.updateUser.userName).toEqual(user.userName);
|
expect(metadataDto.updateUser.username).toEqual(user.username);
|
||||||
expect(metadataDto.viewCount).toEqual(note.viewCount);
|
expect(metadataDto.viewCount).toEqual(note.viewCount);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -798,7 +798,7 @@ describe('NotesService', () => {
|
||||||
const author = Author.create(1);
|
const author = Author.create(1);
|
||||||
author.user = user;
|
author.user = user;
|
||||||
const otherUser = User.create('other hardcoded', 'Testy2') as User;
|
const otherUser = User.create('other hardcoded', 'Testy2') as User;
|
||||||
otherUser.userName = 'other hardcoded user';
|
otherUser.username = 'other hardcoded user';
|
||||||
const group = Group.create('testGroup', 'testGroup');
|
const group = Group.create('testGroup', 'testGroup');
|
||||||
const content = 'testContent';
|
const content = 'testContent';
|
||||||
jest
|
jest
|
||||||
|
@ -872,14 +872,14 @@ describe('NotesService', () => {
|
||||||
expect(noteDto.metadata.createTime).toEqual(revisions[0].createdAt);
|
expect(noteDto.metadata.createTime).toEqual(revisions[0].createdAt);
|
||||||
expect(noteDto.metadata.description).toEqual(note.description);
|
expect(noteDto.metadata.description).toEqual(note.description);
|
||||||
expect(noteDto.metadata.editedBy).toHaveLength(1);
|
expect(noteDto.metadata.editedBy).toHaveLength(1);
|
||||||
expect(noteDto.metadata.editedBy[0]).toEqual(user.userName);
|
expect(noteDto.metadata.editedBy[0]).toEqual(user.username);
|
||||||
expect(noteDto.metadata.permissions.owner.userName).toEqual(
|
expect(noteDto.metadata.permissions.owner.username).toEqual(
|
||||||
user.userName,
|
user.username,
|
||||||
);
|
);
|
||||||
expect(noteDto.metadata.permissions.sharedToUsers).toHaveLength(1);
|
expect(noteDto.metadata.permissions.sharedToUsers).toHaveLength(1);
|
||||||
expect(
|
expect(
|
||||||
noteDto.metadata.permissions.sharedToUsers[0].user.userName,
|
noteDto.metadata.permissions.sharedToUsers[0].user.username,
|
||||||
).toEqual(user.userName);
|
).toEqual(user.username);
|
||||||
expect(noteDto.metadata.permissions.sharedToUsers[0].canEdit).toEqual(
|
expect(noteDto.metadata.permissions.sharedToUsers[0].canEdit).toEqual(
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
@ -893,7 +893,7 @@ describe('NotesService', () => {
|
||||||
expect(noteDto.metadata.tags).toHaveLength(1);
|
expect(noteDto.metadata.tags).toHaveLength(1);
|
||||||
expect(noteDto.metadata.tags[0]).toEqual(note.tags[0].name);
|
expect(noteDto.metadata.tags[0]).toEqual(note.tags[0].name);
|
||||||
expect(noteDto.metadata.updateTime).toEqual(revisions[0].createdAt);
|
expect(noteDto.metadata.updateTime).toEqual(revisions[0].createdAt);
|
||||||
expect(noteDto.metadata.updateUser.userName).toEqual(user.userName);
|
expect(noteDto.metadata.updateUser.username).toEqual(user.username);
|
||||||
expect(noteDto.metadata.viewCount).toEqual(note.viewCount);
|
expect(noteDto.metadata.viewCount).toEqual(note.viewCount);
|
||||||
expect(noteDto.content).toEqual(content);
|
expect(noteDto.content).toEqual(content);
|
||||||
});
|
});
|
||||||
|
|
|
@ -390,7 +390,7 @@ export class NotesService {
|
||||||
title: note.title ?? '',
|
title: note.title ?? '',
|
||||||
createTime: (await this.getFirstRevision(note)).createdAt,
|
createTime: (await this.getFirstRevision(note)).createdAt,
|
||||||
description: note.description ?? '',
|
description: note.description ?? '',
|
||||||
editedBy: (await this.getAuthorUsers(note)).map((user) => user.userName),
|
editedBy: (await this.getAuthorUsers(note)).map((user) => user.username),
|
||||||
permissions: this.toNotePermissionsDto(note),
|
permissions: this.toNotePermissionsDto(note),
|
||||||
tags: this.toTagList(note),
|
tags: this.toTagList(note),
|
||||||
updateTime: (await this.getLatestRevision(note)).createdAt,
|
updateTime: (await this.getLatestRevision(note)).createdAt,
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class EditDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ApiPropertyOptional()
|
@ApiPropertyOptional()
|
||||||
userName: UserInfoDto['userName'] | null;
|
username: UserInfoDto['username'] | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Character index of the start of this section
|
* Character index of the start of this section
|
||||||
|
|
|
@ -106,7 +106,7 @@ createConnection({
|
||||||
}
|
}
|
||||||
for (const user of foundUsers) {
|
for (const user of foundUsers) {
|
||||||
console.log(
|
console.log(
|
||||||
`Created User '${user.userName}' with password '${password}'`,
|
`Created User '${user.username}' with password '${password}'`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (const note of foundNotes) {
|
for (const note of foundNotes) {
|
||||||
|
@ -117,7 +117,7 @@ createConnection({
|
||||||
const historyEntry = HistoryEntry.create(user, note);
|
const historyEntry = HistoryEntry.create(user, note);
|
||||||
await connection.manager.save(historyEntry);
|
await connection.manager.save(historyEntry);
|
||||||
console.log(
|
console.log(
|
||||||
`Created HistoryEntry for user '${user.userName}' and note '${
|
`Created HistoryEntry for user '${user.username}' and note '${
|
||||||
note.aliases[0].name ?? ''
|
note.aliases[0].name ?? ''
|
||||||
}'`,
|
}'`,
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,7 @@ export class UserInfoDto {
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
userName: string;
|
username: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The display name
|
* The display name
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class User {
|
||||||
@Column({
|
@Column({
|
||||||
unique: true,
|
unique: true,
|
||||||
})
|
})
|
||||||
userName: string;
|
username: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
displayName: string;
|
displayName: string;
|
||||||
|
@ -77,14 +77,14 @@ export class User {
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(
|
public static create(
|
||||||
userName: string,
|
username: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
): Pick<
|
): Pick<
|
||||||
User,
|
User,
|
||||||
'userName' | 'displayName' | 'ownedNotes' | 'authTokens' | 'identities'
|
'username' | 'displayName' | 'ownedNotes' | 'authTokens' | 'identities'
|
||||||
> {
|
> {
|
||||||
const newUser = new User();
|
const newUser = new User();
|
||||||
newUser.userName = userName;
|
newUser.username = username;
|
||||||
newUser.displayName = displayName;
|
newUser.displayName = displayName;
|
||||||
return newUser;
|
return newUser;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('UsersService', () => {
|
||||||
});
|
});
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const user = await service.createUser(username, displayname);
|
const user = await service.createUser(username, displayname);
|
||||||
expect(user.userName).toEqual(username);
|
expect(user.username).toEqual(username);
|
||||||
expect(user.displayName).toEqual(displayname);
|
expect(user.displayName).toEqual(displayname);
|
||||||
});
|
});
|
||||||
it('fails if username is already taken', async () => {
|
it('fails if username is already taken', async () => {
|
||||||
|
@ -110,7 +110,7 @@ describe('UsersService', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
const getUser = await service.getUserByUsername(username);
|
const getUser = await service.getUserByUsername(username);
|
||||||
expect(getUser.userName).toEqual(username);
|
expect(getUser.username).toEqual(username);
|
||||||
expect(getUser.displayName).toEqual(displayname);
|
expect(getUser.displayName).toEqual(displayname);
|
||||||
});
|
});
|
||||||
it('fails when user does not exits', async () => {
|
it('fails when user does not exits', async () => {
|
||||||
|
@ -144,7 +144,7 @@ describe('UsersService', () => {
|
||||||
const user = User.create(username, displayname) as User;
|
const user = User.create(username, displayname) as User;
|
||||||
it('works if a user is provided', () => {
|
it('works if a user is provided', () => {
|
||||||
const userDto = service.toUserDto(user);
|
const userDto = service.toUserDto(user);
|
||||||
expect(userDto.userName).toEqual(username);
|
expect(userDto.username).toEqual(username);
|
||||||
expect(userDto.displayName).toEqual(displayname);
|
expect(userDto.displayName).toEqual(displayname);
|
||||||
expect(userDto.photo).toEqual('');
|
expect(userDto.photo).toEqual('');
|
||||||
expect(userDto.email).toEqual('');
|
expect(userDto.email).toEqual('');
|
||||||
|
|
|
@ -24,37 +24,37 @@ export class UsersService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Create a new user with a given userName and displayName
|
* Create a new user with a given username and displayName
|
||||||
* @param userName - the userName the new user shall have
|
* @param username - the username the new user shall have
|
||||||
* @param displayName - the display the new user shall have
|
* @param displayName - the display the new user shall have
|
||||||
* @return {User} the user
|
* @return {User} the user
|
||||||
* @throws {AlreadyInDBError} the userName is already taken.
|
* @throws {AlreadyInDBError} the username is already taken.
|
||||||
*/
|
*/
|
||||||
async createUser(userName: string, displayName: string): Promise<User> {
|
async createUser(username: string, displayName: string): Promise<User> {
|
||||||
const user = User.create(userName, displayName);
|
const user = User.create(username, displayName);
|
||||||
try {
|
try {
|
||||||
return await this.userRepository.save(user);
|
return await this.userRepository.save(user);
|
||||||
} catch {
|
} catch {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`A user with the username '${userName}' already exists.`,
|
`A user with the username '${username}' already exists.`,
|
||||||
'createUser',
|
'createUser',
|
||||||
);
|
);
|
||||||
throw new AlreadyInDBError(
|
throw new AlreadyInDBError(
|
||||||
`A user with the username '${userName}' already exists.`,
|
`A user with the username '${username}' already exists.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Delete the user with the specified userName
|
* Delete the user with the specified username
|
||||||
* @param {User} user - the username of the user to be delete
|
* @param {User} user - the username of the user to be delete
|
||||||
* @throws {NotInDBError} the userName has no user associated with it.
|
* @throws {NotInDBError} the username has no user associated with it.
|
||||||
*/
|
*/
|
||||||
async deleteUser(user: User): Promise<void> {
|
async deleteUser(user: User): Promise<void> {
|
||||||
await this.userRepository.remove(user);
|
await this.userRepository.remove(user);
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Successfully deleted user with username ${user.userName}`,
|
`Successfully deleted user with username ${user.username}`,
|
||||||
'deleteUser',
|
'deleteUser',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -73,20 +73,20 @@ export class UsersService {
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Get the user specified by the username
|
* Get the user specified by the username
|
||||||
* @param {string} userName the username by which the user is specified
|
* @param {string} username the username by which the user is specified
|
||||||
* @param {UserRelationEnum[]} [withRelations=[]] if the returned user object should contain certain relations
|
* @param {UserRelationEnum[]} [withRelations=[]] if the returned user object should contain certain relations
|
||||||
* @return {User} the specified user
|
* @return {User} the specified user
|
||||||
*/
|
*/
|
||||||
async getUserByUsername(
|
async getUserByUsername(
|
||||||
userName: string,
|
username: string,
|
||||||
withRelations: UserRelationEnum[] = [],
|
withRelations: UserRelationEnum[] = [],
|
||||||
): Promise<User> {
|
): Promise<User> {
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({
|
||||||
where: { userName: userName },
|
where: { username: username },
|
||||||
relations: withRelations,
|
relations: withRelations,
|
||||||
});
|
});
|
||||||
if (user === undefined) {
|
if (user === undefined) {
|
||||||
throw new NotInDBError(`User with username '${userName}' not found`);
|
throw new NotInDBError(`User with username '${username}' not found`);
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ export class UsersService {
|
||||||
*/
|
*/
|
||||||
toUserDto(user: User): UserInfoDto {
|
toUserDto(user: User): UserInfoDto {
|
||||||
return {
|
return {
|
||||||
userName: user.userName,
|
username: user.username,
|
||||||
displayName: user.displayName,
|
displayName: user.displayName,
|
||||||
photo: this.getPhotoUrl(user),
|
photo: this.getPhotoUrl(user),
|
||||||
email: user.email ?? '',
|
email: user.email ?? '',
|
||||||
|
|
|
@ -136,7 +136,7 @@ describe('History', () => {
|
||||||
const userEntries = await historyService.getEntriesByUser(user);
|
const userEntries = await historyService.getEntriesByUser(user);
|
||||||
expect(userEntries.length).toEqual(1);
|
expect(userEntries.length).toEqual(1);
|
||||||
expect(userEntries[0].note.aliases).toEqual(note2.aliases);
|
expect(userEntries[0].note.aliases).toEqual(note2.aliases);
|
||||||
expect(userEntries[0].user.userName).toEqual(user.userName);
|
expect(userEntries[0].user.username).toEqual(user.username);
|
||||||
expect(userEntries[0].pinStatus).toEqual(pinStatus);
|
expect(userEntries[0].pinStatus).toEqual(pinStatus);
|
||||||
expect(userEntries[0].updatedAt).toEqual(lastVisited);
|
expect(userEntries[0].updatedAt).toEqual(lastVisited);
|
||||||
});
|
});
|
||||||
|
@ -184,8 +184,8 @@ describe('History', () => {
|
||||||
const historyEntries = await historyService.getEntriesByUser(user);
|
const historyEntries = await historyService.getEntriesByUser(user);
|
||||||
expect(historyEntries).toHaveLength(1);
|
expect(historyEntries).toHaveLength(1);
|
||||||
expect(historyEntries[0].note.aliases).toEqual(prevEntry.note.aliases);
|
expect(historyEntries[0].note.aliases).toEqual(prevEntry.note.aliases);
|
||||||
expect(historyEntries[0].user.userName).toEqual(
|
expect(historyEntries[0].user.username).toEqual(
|
||||||
prevEntry.user.userName,
|
prevEntry.user.username,
|
||||||
);
|
);
|
||||||
expect(historyEntries[0].pinStatus).toEqual(prevEntry.pinStatus);
|
expect(historyEntries[0].pinStatus).toEqual(prevEntry.pinStatus);
|
||||||
expect(historyEntries[0].updatedAt).toEqual(prevEntry.updatedAt);
|
expect(historyEntries[0].updatedAt).toEqual(prevEntry.updatedAt);
|
||||||
|
|
|
@ -20,7 +20,6 @@ import mediaConfigMock from '../../src/config/mock/media.config.mock';
|
||||||
import { GroupsModule } from '../../src/groups/groups.module';
|
import { GroupsModule } from '../../src/groups/groups.module';
|
||||||
import { HistoryEntryUpdateDto } from '../../src/history/history-entry-update.dto';
|
import { HistoryEntryUpdateDto } from '../../src/history/history-entry-update.dto';
|
||||||
import { HistoryEntryDto } from '../../src/history/history-entry.dto';
|
import { HistoryEntryDto } from '../../src/history/history-entry.dto';
|
||||||
import { HistoryEntry } from '../../src/history/history-entry.entity';
|
|
||||||
import { HistoryModule } from '../../src/history/history.module';
|
import { HistoryModule } from '../../src/history/history.module';
|
||||||
import { HistoryService } from '../../src/history/history.service';
|
import { HistoryService } from '../../src/history/history.service';
|
||||||
import { LoggerModule } from '../../src/logger/logger.module';
|
import { LoggerModule } from '../../src/logger/logger.module';
|
||||||
|
@ -217,7 +216,7 @@ describe('Me', () => {
|
||||||
const noteMetaDtos = response.body as NoteMetadataDto[];
|
const noteMetaDtos = response.body as NoteMetadataDto[];
|
||||||
expect(noteMetaDtos).toHaveLength(1);
|
expect(noteMetaDtos).toHaveLength(1);
|
||||||
expect(noteMetaDtos[0].primaryAlias).toEqual(noteName);
|
expect(noteMetaDtos[0].primaryAlias).toEqual(noteName);
|
||||||
expect(noteMetaDtos[0].updateUser?.userName).toEqual(user.userName);
|
expect(noteMetaDtos[0].updateUser?.username).toEqual(user.username);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('GET /me/media', async () => {
|
it('GET /me/media', async () => {
|
||||||
|
|
|
@ -201,7 +201,7 @@ describe('Notes', () => {
|
||||||
const updateNotePermission = new NotePermissionsUpdateDto();
|
const updateNotePermission = new NotePermissionsUpdateDto();
|
||||||
updateNotePermission.sharedToUsers = [
|
updateNotePermission.sharedToUsers = [
|
||||||
{
|
{
|
||||||
username: user.userName,
|
username: user.username,
|
||||||
canEdit: true,
|
canEdit: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -214,8 +214,8 @@ describe('Notes', () => {
|
||||||
expect(updatedNote.userPermissions[0].canEdit).toEqual(
|
expect(updatedNote.userPermissions[0].canEdit).toEqual(
|
||||||
updateNotePermission.sharedToUsers[0].canEdit,
|
updateNotePermission.sharedToUsers[0].canEdit,
|
||||||
);
|
);
|
||||||
expect(updatedNote.userPermissions[0].user.userName).toEqual(
|
expect(updatedNote.userPermissions[0].user.username).toEqual(
|
||||||
user.userName,
|
user.username,
|
||||||
);
|
);
|
||||||
expect(updatedNote.groupPermissions).toHaveLength(0);
|
expect(updatedNote.groupPermissions).toHaveLength(0);
|
||||||
await request(app.getHttpServer()).delete('/notes/test3').expect(204);
|
await request(app.getHttpServer()).delete('/notes/test3').expect(204);
|
||||||
|
@ -280,13 +280,13 @@ describe('Notes', () => {
|
||||||
expect(metadata.body.description).toEqual('');
|
expect(metadata.body.description).toEqual('');
|
||||||
expect(typeof metadata.body.createTime).toEqual('string');
|
expect(typeof metadata.body.createTime).toEqual('string');
|
||||||
expect(metadata.body.editedBy).toEqual([]);
|
expect(metadata.body.editedBy).toEqual([]);
|
||||||
expect(metadata.body.permissions.owner.userName).toEqual('hardcoded');
|
expect(metadata.body.permissions.owner.username).toEqual('hardcoded');
|
||||||
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
||||||
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
||||||
expect(metadata.body.tags).toEqual([]);
|
expect(metadata.body.tags).toEqual([]);
|
||||||
expect(typeof metadata.body.updateTime).toEqual('string');
|
expect(typeof metadata.body.updateTime).toEqual('string');
|
||||||
expect(typeof metadata.body.updateUser.displayName).toEqual('string');
|
expect(typeof metadata.body.updateUser.displayName).toEqual('string');
|
||||||
expect(typeof metadata.body.updateUser.userName).toEqual('string');
|
expect(typeof metadata.body.updateUser.username).toEqual('string');
|
||||||
expect(typeof metadata.body.updateUser.email).toEqual('string');
|
expect(typeof metadata.body.updateUser.email).toEqual('string');
|
||||||
expect(typeof metadata.body.updateUser.photo).toEqual('string');
|
expect(typeof metadata.body.updateUser.photo).toEqual('string');
|
||||||
expect(typeof metadata.body.viewCount).toEqual('number');
|
expect(typeof metadata.body.viewCount).toEqual('number');
|
||||||
|
|
Loading…
Reference in a new issue