/music-store

🎻 Conduct your music empire! 🎧 Tuneful Tunes is your one-stop API to manage artists, albums, and songs. ✨ Search, filter, integrate - it's your musical symphony. 🎶

Primary LanguageTypeScriptMIT LicenseMIT

music-store-high-resolution-logo-color-on-transparent-background



Music Store

📑 Table of Contents

📘 Introduction

🎻 Conduct your music empire! 🎧 Music Store is your one-stop API to manage artists, albums, and songs. ✨ Search, filter, integrate - it's your musical symphony. 🎶

Welcome to Music Store API, a powerful and efficient REST API built with NestJS that serves as your ultimate solution for managing your music empire. With Music Store API, you can easily organize and control your artists, albums, and songs, creating a seamless and immersive musical experience for your users.

Music Store API prioritizes the security and reliability of your music assets. The API implements robust authentication mechanisms, ensuring secure access to your music collection. With built-in security features, you can protect sensitive data and provide a safe environment for your users' musical journey.

💻 Getting Started

To get a local copy up and running, follow these steps.

Prerequisites ❗

In order to run this project you need:

Environment Variables 🔑

  • DATABASE_HOST: the mysql host (e.g. localhost)
  • DATABASE_PORT: the port on which mysql are working on (e.g. 3306)
  • DATABASE_USERNAME: your mysql username (e.g. mysql)
  • DATABASE_PASSWORD: your mysql password (e.g. root)
  • DATABASE_NAME: the database name on which the project will use (e.g. MusicStore)
  • JWT_SECRET: the json web token signature to create or validate token (e.g. jwtsecret)
  • COOKIE_SESSION_SECRET: your cookie session secret (e.g sessionsecret)

Setup ⬇️

  1. Clone the repository:
   git clone https://github.com/ahmedeid6842/music-store
  1. Change to the project directory:
cd ./music-store

Install ✔️

Install the project dependencies using NPM:

npm install

Usage 🤿 🏃‍♂️

To start the application in development mode, run the following command:

npm run start:dev

The application will be accessible at http://localhost:3000.

  • Alright, it's showtime! 🔥 Hit http://localhost:3000 and BOOM! 💥 You should see the docs page and the Music Store APIs working flawlessly. ✨🧙‍♂️

(back to top)

This section provides detailed documentation and examples for the API endpoints used in the Music Store backend project. You can Hit this Link to view the documentation. Screenshot from 2023-12-07 21-30-57

🏗️🔨 Database ERD

ERD-V2

(back to top)

🔄 Authentication Sequence Diagrams

Auth Module

sequenceDiagram
    participant User
    participant AuthController
    participant AuthService
    participant UsersService
    participant EmailService
    participant JwtService

    User->>+AuthController: register()
    AuthController->>+AuthService: register(userCredentials)
    AuthService->>+UsersService: createUser(userCredentials)
    UsersService-->>-AuthService: user
    AuthService->>+EmailService: sendRegistrationEmail(user)
    EmailService-->>-AuthService: emailSent
    AuthService-->>-AuthController: registrationSuccess

    User->>+AuthController: login(credentials)
    AuthController->>+AuthService: login(credentials)
    AuthService->>+UsersService: getUserByEmail(email)
    UsersService-->>-AuthService: user
    AuthService->>+AuthService: comparePasswords(password, user.password)
    AuthService->>+JwtService: generateToken(user)
    JwtService-->>-AuthService: token
    AuthService-->>-AuthController: loginSuccess(token)

    User->>+AuthController: requestPasswordReset(email)
    AuthController->>+AuthService: requestPasswordReset(email)
    AuthService->>+UsersService: getUserByEmail(email)
    UsersService-->>-AuthService: user
    AuthService->>+AuthService: generatePasswordResetToken(user)
    AuthService->>+EmailService: sendPasswordResetEmail(user, resetToken)
    EmailService-->>-AuthService: emailSent
    AuthService-->>-AuthController: passwordResetEmailSent()

    User->>+AuthController: resetPassword(resetToken, newPassword)
    AuthController->>+AuthService: resetPassword(resetToken, newPassword)
    AuthService->>+AuthService: verifyPasswordResetToken(resetToken)
    AuthService->>+UsersService: getUserById(userId)
    UsersService-->>-AuthService: user
    AuthService->>+AuthService: hashPassword(newPassword)
    AuthService->>+UsersService: updatePassword(user, hashedPassword)
    UsersService-->>-AuthService: updatedUser
    AuthService-->>-AuthController: passwordResetSuccess()

    User->>+AuthController: verifyEmail(email, verificationCode)
    AuthController->>+AuthService: verifyEmail(email, verificationCode)
    AuthService->>+UsersService: getUserByEmail(email)
    UsersService-->>-AuthService: user
    AuthService->>+AuthService: verifyEmail(user, verificationCode)
    AuthService->>+UsersService: updateUserVerification(user)
    UsersService-->>-AuthService: updatedUser
    AuthService-->>-AuthController: emailVerificationSuccess()

    User->>+AuthController: logout()
    AuthController->>+AuthService: logout()
    AuthService-->>-AuthController: logoutSuccess()

(back to top)

📐 UML Diagram

classDiagram
    class UsersService {
        + create(email: string, userName: string, password: string, verificationCode: string, verificationCodeExpiresAt: Date): void
        + findOne(id: string)
        + find(email?: string, userName?: string)
        + update(userId: string, attrs: Partial<User>)
    }

    class User {
        + id: string
        + email: string
        + userName: string
        + password: string
        + verificationCode: string
        + verificationCodeExpiresAt: Date
    }

    class CreateUserDto {
        + email: string
        + password: string
        + userName: string
    }

    class AuthService {
        + register(userData: CreateUserDto): void
        + verifyEmail(email: string, verificationCode: string): void
        + login(userCredentials: LoginUserDto): string
        + sendResetPasswordEmail(userData: any): void
        + resetPassword(token: string, password: string): void
        - generateResetPasswordToken(userId: string): string
        - generateVerificationCode(): string
        - generateVerificationCodeExpiration(): Date
    }

    class EmailService {
        - email: string
        - password: string
        + sendResetPasswordEmail(email: string, resetPasswordUrl: string): void
        + sendVerificationEmail(email: string, verificationCode: string): void
    }

    class ArtistService {
        + createArtist(artist: CreateArtistDto, user: UserDto): void
        + getArtist(query: GetArtistQueryDto): Artist[]
        + updateArtist(artist: PartialArtistDto, user: UserDto): void
    }

    class Artist {
        + id: string
        + name: string
        + bio: string
        + user: User
    }

    class AlbumService {
        + createAlbum(albumBody: CreateAlbumDto, artist: Artist): void
        + getAlbums(query: GetAlbumQueryDto): Album[]
        + updateAlbum(albumId: string, albumBody: PartialAlbumDto): void
        + deleteAlbum(albumId: string): void
    }

    class Album {
        + id: string
        + title: string
        + artworkUrl: string
        + artist: Artist
    }

    class SongService {
        + createSong(newSong: CreateSongDto, artist: Artist): void
        + getSongs(query: GetSongQueryDto): Song[]
        + updateSong(songId: string, newSong: PartialSongDto): void
        + deleteSong(songId: string): void
    }

    class Song {
        + id: string
        + title: string
        + duration: number
        + album: Album
        + artists: Artist[]
    }

    UsersService --> User: Manages
    AuthService --> UsersService: Depends on
    AuthService --> EmailService: Depends on
    ArtistService --> Artist: Manages
    ArtistService --> UsersService: Uses
    AlbumService --> Album: Manages
    AlbumService --> ArtistService: Uses
    SongService --> ArtistService: Uses
    SongService --> Song: Manages

(back to top)

👤 Author

Ahmed Eid 🙋‍♂️

(back to top)

🤝 Contributing

We're always looking to improve this project! 🔍 If you notice any issues or have ideas for new features, please don't hesitate to submit a pull request 🙌 or create a new issue 💡. Your contribution will help make this project even better! ❤️ 💪

👀 Kanban Board

You can check my kanban board from Here to see how I split this project into tasks and mange them.

kanban board image

⭐️ Show your support

If you find this project helpful, I would greatly appreciate it if you could leave a star! 🌟 💟

(back to top)

🔭 Up next

  • Implement Search engine for different songs searches
  • Enhance the DataBase queries time by using redis LRU caching
  • Move from monolithic to microservices architecture.
  • Apply Background jobs and task scheduling Use a job queue system like Bull or Agenda to handle time-consuming tasks.
  • Support user media like image and upload songs.
  • Deploy the REST API.

💎 Lessons Learned

  1. Secure user access with effective authentication and authorization.
  2. Use a well-structured architecture, such as Nest.js, for code organization, scalability, and maintainability.
  3. Take advantage of different NestJS components and decorators.
  4. Manging the Many to Many relations
  5. There is always something new to learn.

🙏 Acknowledgments

I am deeply grateful to Alexapps for entrusting me with this project. The opportunity to implement this innovative concept has been an invaluable learning experience.

📜 License

This project is licensed under the MIT License - you can click here to have more details MIT licensed.

(back to top)