Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User profiles #29

Draft
wants to merge 61 commits into
base: develop
Choose a base branch
from
Draft
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
370757f
refactor: reorganize imports and update endpoint routes in UserContro…
tomast1337 Jan 12, 2025
71c15bd
feat: add UpdateUserProfile DTO and validation for social media links
tomast1337 Jan 12, 2025
2677c07
feat: add updateProfile endpoint and service method in UserController…
tomast1337 Jan 12, 2025
b54021d
feat: add deepFreeze function and corresponding tests for object immu…
tomast1337 Jan 12, 2025
1d8fe63
refactor: remove IsNotEmpty validation from UpdateUsername DTO
tomast1337 Jan 12, 2025
a766f69
feat: integrate deepFreeze for LinkRegexes in UpdateUserProfile DTO
tomast1337 Jan 12, 2025
288156f
feat: implement updateProfile method in UserService and corresponding…
tomast1337 Jan 12, 2025
981239e
feat: add localhost configuration for development in next.config.mjs
tomast1337 Jan 15, 2025
6e2826f
feat: add BlockSearch component and integrate it into the Header
tomast1337 Jan 15, 2025
4240d89
refactor: change Header component to a constant and add IDs for acces…
tomast1337 Jan 16, 2025
2b6490f
feat: create SearchPage component to display search parameter
tomast1337 Jan 16, 2025
fee4223
Merge branch 'develop' into feature/user-profile
tomast1337 Jan 20, 2025
0f479df
feat: add UserViewDto class for user profile data validation
tomast1337 Jan 20, 2025
776652a
feat: add SearchQueryDTO for search query validation and pagination
tomast1337 Jan 20, 2025
0bcd28c
feat: implement search functionality in SongService with pagination a…
tomast1337 Jan 20, 2025
c22cb53
feat: add createdAt and updatedAt fields to User entity
tomast1337 Jan 20, 2025
3427d57
feat: implement user search functionality with pagination and indexing
tomast1337 Jan 20, 2025
c642e26
feat: implement search functionality in SearchService and SearchContr…
tomast1337 Jan 20, 2025
46d8b32
feat: add SearchModule to the application module
tomast1337 Jan 20, 2025
dedb9ae
feat: update SearchQueryDTO to make query parameters optional
tomast1337 Jan 21, 2025
30c1d24
feat: update search controller to use SearchQueryDTO for query parame…
tomast1337 Jan 21, 2025
b070a76
feat: enhance SearchModule to initialize indexes and improve logging …
tomast1337 Jan 21, 2025
7aa68c6
feat: enhance song and user services to support regex search and impr…
tomast1337 Jan 21, 2025
2af37e7
feat: optimize search functionality in song and user services with ag…
tomast1337 Jan 21, 2025
e4b3a80
feat: refactor search services to use text search and improve logging…
tomast1337 Jan 24, 2025
60efd8d
Merge branch 'main' into feature/user-profile
Bentroen Feb 20, 2025
f52bdcb
style: import order and separation
Bentroen Mar 2, 2025
f4cadb0
chore: set window title to workspace name in VS Code workspace settings
Bentroen Mar 2, 2025
94119ce
feat: re-enable user page and add route for getting user data by user…
Bentroen Mar 2, 2025
23b7f2d
style: enforce blank line between class methods
Bentroen Mar 2, 2025
c85f823
refactor: drop fields that will no longer be stored in the user entity
Bentroen Mar 2, 2025
0380f04
style: add comment about auto-added mongoose timestamps
Bentroen Mar 2, 2025
1ed32cb
refactor: drop fields that will no longer be stored in the user entity
Bentroen Mar 2, 2025
5d7252b
Merge branch 'main' into feature/user-profile
Bentroen Mar 2, 2025
eba38e4
refactor: rename `UserViewDto` to `UserPreviewDto` and create new DTO…
Bentroen Mar 3, 2025
c44287a
feat: add link to user profile in song page user badge
Bentroen Mar 3, 2025
b3bf329
feat: add link to user profile in song card widget
Bentroen Mar 3, 2025
6c00f79
feat: add filter by user in song controller GET method
Bentroen Mar 5, 2025
6c663a7
fix: return 404 if user not found instead of malformed request error
Bentroen Mar 5, 2025
1ebde28
style: add comment, whitespace
Bentroen Mar 5, 2025
06ca764
feat: add user page layout with initial user song fetching
Bentroen Mar 5, 2025
8cc0bcb
chore: adjust eslint settings to avoid hanging during lint
Bentroen Mar 5, 2025
f4a73ed
chore: update `.git-blame-ignore-revs`
Bentroen Mar 5, 2025
f8244c9
fix: ad filling error causing frontend crash
Bentroen Mar 6, 2025
67203ce
fix: hydration error due to nested `<a>` tag in `SongCard` component
Bentroen Mar 7, 2025
b24f421
test: fix `SongService` tests for new query by user method
Bentroen Mar 7, 2025
753a933
refactor: tidy up API methods for `UserController`
Bentroen Mar 7, 2025
3e5c840
Merge branch 'main' into feature/user-profile
Bentroen Mar 8, 2025
e48b098
chore: add `zustand` to dependencies
Bentroen Mar 8, 2025
22378f2
Merge branch 'develop' of https://github.com/OpenNBS/NoteBlockWorld i…
tomast1337 Mar 15, 2025
6434681
feat: update PageQueryDTO to use 'query' for filtering and add UserQu…
tomast1337 Mar 15, 2025
820d6b3
feat: replace old SearchPage component with new SearchPage implementa…
tomast1337 Mar 15, 2025
1f445fe
feat: implement SearchPageComponent and useSearch context for search …
tomast1337 Mar 15, 2025
9fea0c8
chore: update workspace configuration for improved settings and folde…
tomast1337 Mar 15, 2025
dfa1258
feat: enhance user profile functionality with social links and error …
tomast1337 Mar 15, 2025
b5bb1f3
refactor: remove deprecated search module and related components
tomast1337 Mar 15, 2025
087af4c
feat: implement user search functionality with pagination and song count
tomast1337 Mar 15, 2025
44b3259
feat: add PageResultDTO and UserSearchViewDto for user search functio…
tomast1337 Mar 15, 2025
b898ab1
feat: implement user search page with user cards and pagination
tomast1337 Mar 15, 2025
ff9a543
feat: integrate router for search results navigation and update query…
tomast1337 Mar 15, 2025
09a8a6d
feat: update user profile page title and enable navigation from user …
tomast1337 Mar 15, 2025
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
12 changes: 9 additions & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -2,10 +2,11 @@ module.exports = {
ignorePatterns: ['.eslintrc.js'],
parserOptions: {
parser: '@typescript-eslint/parser',
project: './tsconfig.json',
project: ['./tsconfig.json', './*/tsconfig.json'],
tsconfigRootDir: __dirname,
sourceType: 'module',
ecmaVersion: 2021,
createDefaultProgram: false,
},
plugins: ['@typescript-eslint', 'prettier', 'import', 'unused-imports'], // Merged plugins from both files
extends: [
@@ -36,8 +37,13 @@ module.exports = {
],
'@typescript-eslint/lines-between-class-members': [
'warn',
'always',
{ exceptAfterSingleLine: true },
{
enforce: [
{ blankLine: 'any', prev: '*', next: 'field' },
{ blankLine: 'any', prev: 'field', next: '*' },
{ blankLine: 'always', prev: '*', next: 'method' },
],
},
],
'padding-line-between-statements': 'off',
'@typescript-eslint/padding-line-between-statements': [
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -3,3 +3,5 @@

# Linting commits
6efc953b9f7f648f2be59295a78ce1180f12b32d
f52bdcb555ffa1ed02ae8918b04500c9cee52bfd
23b7f2d5ca99b69ea1e50667fdb9c9795d55195f
78 changes: 44 additions & 34 deletions NoteBlockWorld.code-workspace
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
{
"folders": [
{
"path": ".",
"name": "Root"
},
{
"path": "./server",
"name": "Backend"
},
{
"path": "./shared",
"name": "Shared"
},
{
"path": "./web",
"name": "Frontend"
"folders": [
{
"path": ".",
"name": "Root"
},
{
"path": "./server",
"name": "Backend"
},
{
"path": "./shared",
"name": "Shared"
},
{
"path": "./web",
"name": "Frontend"
}
],
"settings": {
"window.title": "${dirty}${rootName}",
"editor.formatOnSave": true,
"eslint.validate": [
"typescript"
],
"eslint.run": "onType",
"eslint.format.enable": true,
"mdx.server.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"jest.disabledWorkspaceFolders": [
"Root",
"Frontend"
],
"search.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/dist": true,
},
"cSpell.words": [
"Bentroen",
"Tomast"
]
}
],
"settings": {
"editor.formatOnSave": true,
"eslint.validate": ["typescript"],
"eslint.run": "onType",
"eslint.format.enable": true,
"mdx.server.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"jest.disabledWorkspaceFolders": ["Root", "Frontend"],
"search.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/dist": true,
}
}
}
}
26 changes: 26 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ import { MagicLinkEmailStrategy } from './strategies/magicLinkEmail.strategy';
@ApiTags('auth')
export class AuthController {
private readonly logger = new Logger(AuthController.name);

constructor(
@Inject(AuthService)
private readonly authService: AuthService,
1 change: 1 addition & 0 deletions server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ import { TokenPayload, Tokens } from './types/token';
@Injectable()
export class AuthService {
private readonly logger = new Logger(AuthService.name);

constructor(
@Inject(UserService)
private readonly userService: UserService,
1 change: 1 addition & 0 deletions server/src/auth/strategies/JWT.strategy.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import { ExtractJwt, Strategy } from 'passport-jwt';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt-refresh') {
private static logger = new Logger(JwtStrategy.name);

constructor(@Inject(ConfigService) config: ConfigService) {
const JWT_SECRET = config.getOrThrow('JWT_SECRET');

1 change: 1 addition & 0 deletions server/src/auth/strategies/discord.strategy/Strategy.ts
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ export default class Strategy extends OAuth2Strategy {
private fetchScopeEnabled: boolean;
public override name = 'discord';
prompt?: string;

public constructor(options: DiscordStrategyConfig, verify: VerifyFunction) {
super(
{
1 change: 1 addition & 0 deletions server/src/auth/strategies/discord.strategy/index.ts
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import { DiscordPermissionScope } from './types';
@Injectable()
export class DiscordStrategy extends PassportStrategy(strategy, 'discord') {
private static logger = new Logger(DiscordStrategy.name);

constructor(
@Inject(ConfigService)
configService: ConfigService,
1 change: 1 addition & 0 deletions server/src/auth/strategies/github.strategy.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import strategy from 'passport-github';
@Injectable()
export class GithubStrategy extends PassportStrategy(strategy, 'github') {
private static logger = new Logger(GithubStrategy.name);

constructor(
@Inject(ConfigService)
configService: ConfigService,
1 change: 1 addition & 0 deletions server/src/auth/strategies/google.strategy.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { Strategy, VerifyCallback } from 'passport-google-oauth20';
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
private static logger = new Logger(GoogleStrategy.name);

constructor(
@Inject(ConfigService)
configService: ConfigService,
12 changes: 6 additions & 6 deletions server/src/song/entity/song.entity.ts
Original file line number Diff line number Diff line change
@@ -24,10 +24,10 @@ export class Song {
publicId: string;

@Prop({ type: MongooseSchema.Types.Date, required: true, default: Date.now })
createdAt: Date;
createdAt: Date; // Added automatically by Mongoose: https://mongoosejs.com/docs/timestamps.html

@Prop({ type: MongooseSchema.Types.Date, required: true, default: Date.now })
updatedAt: Date;
updatedAt: Date; // Added automatically by Mongoose: https://mongoosejs.com/docs/timestamps.html

@Prop({ type: MongooseSchema.Types.ObjectId, required: true, ref: 'User' })
uploader: Types.ObjectId;
@@ -57,7 +57,7 @@ export class Song {
@Prop({ type: ThumbnailData, required: true })
thumbnailData: ThumbnailData;

@Prop({ type: String, required: true })
@Prop({ type: String, required: true, index: true })
category: CategoryType;

@Prop({ type: String, required: true })
@@ -72,13 +72,13 @@ export class Song {
@Prop({ type: Boolean, required: true, default: true })
allowDownload: boolean;

@Prop({ type: String, required: true })
@Prop({ type: String, required: true, index: true })
title: string;

@Prop({ type: String, required: false })
@Prop({ type: String, required: false, index: true })
originalAuthor: string;

@Prop({ type: String, required: false })
@Prop({ type: String, required: false, index: true })
description: string;

// SONG FILE ATTRIBUTES (Populated from NBS file - immutable)
13 changes: 13 additions & 0 deletions server/src/song/song.service.spec.ts
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import mongoose, { Model } from 'mongoose';

import { FileService } from '@server/file/file.service';
import { UserDocument } from '@server/user/entity/user.entity';
import { UserService } from '@server/user/user.service';

import {
SongDocument,
@@ -39,10 +40,17 @@ const mockSongWebhookService = {
syncSongWebhook: jest.fn(),
};

const mockUserService = {
getUserByEmailOrId: jest.fn(),
getUserPaginated: jest.fn(),
getSelfUserData: jest.fn(),
};

describe('SongService', () => {
let service: SongService;
let fileService: FileService;
let songUploadService: SongUploadService;
let userService: UserService;
let songModel: Model<SongEntity>;

beforeEach(async () => {
@@ -65,12 +73,17 @@ describe('SongService', () => {
provide: SongUploadService,
useValue: mockSongUploadService,
},
{
provide: UserService,
useValue: mockUserService,
},
],
}).compile();

service = module.get<SongService>(SongService);
fileService = module.get<FileService>(FileService);
songUploadService = module.get<SongUploadService>(SongUploadService);
userService = module.get<UserService>(UserService);
songModel = module.get<Model<SongEntity>>(getModelToken(SongEntity.name));
});

Loading