feat(api): user authentication

This commit is contained in:
Julian Tölle 2020-02-01 16:11:48 +01:00
parent f14eda16ac
commit f253a66f86
41 changed files with 657 additions and 338 deletions

View file

@ -0,0 +1,10 @@
export class CreateOrUpdateDto {
displayName: string;
photo?: string;
spotify: {
id: string;
accessToken: string;
refreshToken: string;
};
}

17
src/users/user.entity.ts Normal file
View file

@ -0,0 +1,17 @@
import { Entity, Column, PrimaryGeneratedColumn, OneToOne } from "typeorm";
import { SpotifyConnection } from "../sources/spotify/spotify-connection.entity";
@Entity()
export class User {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column()
displayName: string;
@Column({ nullable: true })
photo?: string;
@Column(type => SpotifyConnection)
spotify: SpotifyConnection;
}

View file

@ -0,0 +1,5 @@
import { EntityRepository, Repository } from "typeorm";
import { User } from "./user.entity";
@EntityRepository(User)
export class UserRepository extends Repository<User> {}

View file

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
describe('Users Controller', () => {
let controller: UsersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
}).compile();
controller = module.get<UsersController>(UsersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View file

@ -0,0 +1,17 @@
import { Controller, Get } from "@nestjs/common";
import { Auth } from "../auth/decorators/auth.decorator";
import { ReqUser } from "../auth/decorators/req-user.decorator";
import { User } from "./user.entity";
@Controller("api/v1/users")
export class UsersController {
@Get("me")
@Auth()
getMe(@ReqUser() user: User): Omit<User, "spotify"> {
return {
id: user.id,
displayName: user.displayName,
photo: user.photo
};
}
}

13
src/users/users.module.ts Normal file
View file

@ -0,0 +1,13 @@
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { UserRepository } from "./user.repository";
import { UsersService } from "./users.service";
import { UsersController } from './users.controller';
@Module({
imports: [TypeOrmModule.forFeature([UserRepository])],
providers: [UsersService],
exports: [UsersService],
controllers: [UsersController]
})
export class UsersModule {}

View file

@ -0,0 +1,18 @@
import { Test, TestingModule } from "@nestjs/testing";
import { UsersService } from "./users.service";
describe("UsersService", () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService]
}).compile();
service = module.get<UsersService>(UsersService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
});

View file

@ -0,0 +1,42 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { CreateOrUpdateDto } from "./dto/create-or-update.dto";
import { User } from "./user.entity";
import { UserRepository } from "./user.repository";
@Injectable()
export class UsersService {
constructor(private readonly userRepository: UserRepository) {}
async findById(id: string): Promise<User> {
const user = await this.userRepository.findOne(id);
if (!user) {
throw new NotFoundException("UserNotFound");
}
return user;
}
async createOrUpdate(data: CreateOrUpdateDto): Promise<User> {
let user = await this.userRepository.findOne({
where: { spotify: { id: data.spotify.id } }
});
if (!user) {
user = this.userRepository.create({
spotify: {
id: data.spotify.id
}
});
}
user.spotify.accessToken = data.spotify.accessToken;
user.spotify.refreshToken = data.spotify.refreshToken;
user.displayName = data.displayName;
user.photo = data.photo;
await this.userRepository.save(user);
return user;
}
}