src/auth/auth.service.ts
Properties |
|
Methods |
|
constructor(configService: ConfigService, utilService: UtilsService, usersService: UsersService, httpService: HttpService, databaseService: DatabaseService, codesService: CodesService, emailService: EmailsService, discordService: DiscordService, githubService: GithubService)
|
||||||||||||||||||||||||||||||
|
Defined in src/auth/auth.service.ts:30
|
||||||||||||||||||||||||||||||
|
Parameters :
|
| Public createJwt | ||||||
createJwt(payload: string | Object)
|
||||||
|
Defined in src/auth/auth.service.ts:42
|
||||||
|
Parameters :
Returns :
string
|
| Public decodeJwt | ||||||
decodeJwt(jwt?: string)
|
||||||
|
Defined in src/auth/auth.service.ts:52
|
||||||
|
Parameters :
Returns :
string | undefined
|
| Public Async forceLogUserIn | ||||||
forceLogUserIn(user: string)
|
||||||
|
Defined in src/auth/auth.service.ts:112
|
||||||
|
Parameters :
|
| Public Async get2faStatus | ||||||
get2faStatus(snowflake: string)
|
||||||
|
Defined in src/auth/auth.service.ts:220
|
||||||
|
Parameters :
Returns :
Promise<boolean>
|
| Public Async getEmailAndUserValidity | ||||||
getEmailAndUserValidity(snowflake: string | undefined)
|
||||||
|
Defined in src/auth/auth.service.ts:140
|
||||||
|
Parameters :
Returns :
unknown
|
| Private Async getOtpToken | ||||||
getOtpToken(user: string)
|
||||||
|
Defined in src/auth/auth.service.ts:179
|
||||||
|
Parameters :
Returns :
Promise<string | undefined>
|
| Public Async handleDiscordOauthPassW | |||||||||||||||
handleDiscordOauthPassW(dto: SetOauthPassDto, userId: string, tok: string, tokType: string)
|
|||||||||||||||
|
Defined in src/auth/auth.service.ts:270
|
|||||||||||||||
|
Parameters :
Returns :
unknown
|
| Public Async handleGithubOauthPassW | ||||||||||||
handleGithubOauthPassW(dto: SetOauthPassDto, userId: string, tok: string)
|
||||||||||||
|
Defined in src/auth/auth.service.ts:302
|
||||||||||||
|
Parameters :
Returns :
unknown
|
| Public Async initiallyCreate2faToken | ||||||
initiallyCreate2faToken(user: string)
|
||||||
|
Defined in src/auth/auth.service.ts:169
|
||||||
|
Parameters :
Returns :
Promise<Init2faRetVal>
|
| Public Async initResetPass | ||||||
initResetPass(dto: InitResetPassDto)
|
||||||
|
Defined in src/auth/auth.service.ts:232
|
||||||
|
Parameters :
Returns :
unknown
|
| Public Async is2faCodeValid |
is2faCodeValid(user: string, token: string)
|
|
Defined in src/auth/auth.service.ts:189
|
|
Returns :
Promise<boolean>
|
| Public Async isPasswordCorrectForUser |
isPasswordCorrectForUser(user: string, password: string)
|
|
Defined in src/auth/auth.service.ts:210
|
|
Returns :
Promise<boolean>
|
| Public Async resetPass | ||||||
resetPass(dto: ResetPassDto)
|
||||||
|
Defined in src/auth/auth.service.ts:260
|
||||||
|
Parameters :
Returns :
unknown
|
| Public Async toggle2fa |
toggle2fa(user: string, state: boolean)
|
|
Defined in src/auth/auth.service.ts:201
|
|
Returns :
Promise<void>
|
| Private Async update2faToken |
update2faToken(user: string, token: string, codes: string[])
|
|
Defined in src/auth/auth.service.ts:157
|
|
Returns :
any
|
| Public Async validateUser |
validateUser(dto: LoginDto, agent: string)
|
|
Defined in src/auth/auth.service.ts:63
|
|
|
| Public Async verifyCaptcha |
verifyCaptcha(token: string, ip?: string)
|
|
Defined in src/auth/auth.service.ts:125
|
|
Returns :
Promise<boolean>
|
| Private Readonly logger |
Default value : new Logger(AuthService.name)
|
|
Defined in src/auth/auth.service.ts:30
|
import {
forwardRef,
Inject,
Injectable,
Logger,
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as jaywee from 'jsonwebtoken';
import LoginDto from './dto/login.dto';
import { UtilsService } from '../utils/utils.service';
import { UsersService } from '../users/users.service';
import { LoginEnum } from '../utils/enums/responses/login.enum';
import { HttpService } from '@nestjs/axios';
import { GenericResponse, Init2faRetVal } from '../../types';
import { GenericException } from '../exceptions/generic.exception';
import { InvalidUserException } from '../exceptions/invalid.exception';
import * as speakeasy from 'speakeasy';
import { DatabaseService } from '../database/database.service';
import { CodesService } from '../codes/codes.service';
import { InitResetPassDto, ResetPassDto } from './dto/resetpass.dto';
import { EmailsService } from '../emails/emails.service';
import { GenericRespEnum } from '../utils/enums/responses.enum';
import { SetOauthPassDto } from './dto/setpass.dto';
import { DiscordService } from './discord/discord.service';
import { GithubService } from './github/github.service';
@Injectable()
export class AuthService {
private readonly logger = new Logger(AuthService.name);
constructor(
private readonly configService: ConfigService,
private readonly utilService: UtilsService,
private readonly usersService: UsersService,
private readonly httpService: HttpService,
private readonly databaseService: DatabaseService,
private readonly codesService: CodesService,
private readonly emailService: EmailsService,
private readonly discordService: DiscordService,
private readonly githubService: GithubService,
) {}
public createJwt(payload: string | Object): string {
return jaywee.sign(
payload,
this.configService.get<string>('JWT_SECRET') as string,
{
algorithm: 'HS256',
},
);
}
public decodeJwt(jwt?: string): string | undefined {
try {
return jaywee.verify(
jwt || 'oi cunt',
this.configService.get<string>('JWT_SECRET'),
) as string;
} catch (err) {
return undefined;
}
}
public async validateUser(
dto: LoginDto,
agent: string,
): Promise<GenericResponse<LoginEnum, string>> {
//throw new Error("fuck off u daft cunt")
const transformed = this.utilService.transformCredential(dto.username);
dto.username = transformed.value;
const resolvedUser = await this.usersService.getUser(
transformed.value,
transformed.type,
);
if (!resolvedUser) {
throw new GenericException(
this.utilService.Enums.Responses.LoginEnum.ERR_INVALID_CREDS,
);
}
if (!resolvedUser.emailVerified) {
throw new InvalidUserException(true);
}
const pass = await this.usersService.getPassword(resolvedUser.snowflake);
if (await this.utilService.comparePass(dto.password, pass)) {
if (await this.get2faStatus(resolvedUser.snowflake)) {
const code = await this.codesService.createCode(
'TWOFACTOR_AUTH',
10,
resolvedUser.snowflake,
);
return {
message: 'TWOFACTOR_NEEDED',
data: code.code,
};
} else {
const jwt = this.createJwt({
snowflake: resolvedUser.snowflake,
});
this.logger.debug('JWT', jwt);
return {
message: this.utilService.Enums.Responses.LoginEnum.LOGGED_IN,
data: jwt,
};
}
} else {
throw new GenericException(
this.utilService.Enums.Responses.LoginEnum.ERR_INVALID_CREDS,
);
}
}
public async forceLogUserIn(
user: string,
): Promise<GenericResponse<LoginEnum, string>> {
const jwt = this.createJwt({
snowflake: user,
});
this.logger.debug('JWT', jwt);
return {
message: this.utilService.Enums.Responses.LoginEnum.LOGGED_IN,
data: jwt,
};
}
public async verifyCaptcha(token: string, ip?: string): Promise<boolean> {
const r = await this.httpService.post(
'https://www.google.com/recaptcha/api/siteverify',
`secret=${process.env.CAPTCHA}&response=${token}&remoteip=${ip}`,
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
},
},
);
const parsed = await r.toPromise();
return parsed.data.success;
}
public async getEmailAndUserValidity(snowflake: string | undefined) {
if (!snowflake) {
return { valid: false, emailVerified: false };
}
this.logger.debug(`Snowflake: ${snowflake}`);
const valid = await this.usersService.isSnowflakeValid(snowflake, {
email_verified: true,
admin: true,
});
return {
valid: valid.valid,
emailVerified: !!valid?.excessResult?.email_verified,
admin: !!valid.excessResult?.admin,
};
}
private async update2faToken(user: string, token: string, codes: string[]) {
await this.databaseService.write.users.update({
where: { snowflake: user },
data: {
otp_token: token,
recovery_codes: {
push: codes,
},
},
});
}
public async initiallyCreate2faToken(user: string): Promise<Init2faRetVal> {
const secret = speakeasy.generateSecret({
name: 'Fileglass',
issuer: 'Fileglass',
});
const recovery = await this.utilService.createUniformIds(10, 8);
await this.update2faToken(user, secret.base32, recovery);
return { qrcode: secret.otpauth_url!, recovery };
}
private async getOtpToken(user: string): Promise<string | undefined> {
const r = await this.databaseService.read.users.findFirst({
where: { snowflake: user },
select: {
otp_token: true,
},
});
return r?.otp_token || undefined;
}
public async is2faCodeValid(user: string, token: string): Promise<boolean> {
const sec = await this.getOtpToken(user);
if (!sec) {
return true;
}
return speakeasy.totp.verify({
secret: sec,
encoding: 'base32',
token,
});
}
public async toggle2fa(user: string, state: boolean): Promise<void> {
await this.databaseService.write.users.update({
where: { snowflake: user },
data: {
twostep: state,
},
});
}
public async isPasswordCorrectForUser(
user: string,
password: string,
): Promise<boolean> {
const currpass = await this.databaseService.read.users.findFirst({
where: { snowflake: user },
select: { password: true },
});
return await this.utilService.comparePass(password, currpass.password);
}
public async get2faStatus(snowflake: string): Promise<boolean> {
const r = await this.databaseService.read.users.findFirst({
where: {
snowflake,
},
select: {
twostep: true,
},
});
return r.twostep;
}
public async initResetPass(dto: InitResetPassDto) {
const user = await this.usersService.getUser(
this.utilService.sha(dto.email),
'email_hash',
);
if (user?.snowflake) {
this.logger.debug(
'Valid user for email',
dto.email,
'sending password reset email',
);
const username = await this.usersService.getUsername(user.snowflake);
const code = await this.codesService.createCode(
'PASSWORD_RESET',
60,
user.snowflake,
);
const bod = this.emailService.bodies.passResetEmail(
`https://dash.file.glass/resetpassword?q=${code.code}`,
username,
);
await new this.emailService.Mailer(dto.email, 'Reset your password')
.append(bod)
.deliver();
}
return GenericRespEnum.PASS_RESET_SENT;
}
public async resetPass(dto: ResetPassDto) {
const code = await this.codesService.fetchCode(dto.code);
await this.usersService.setFieldData(
code.user,
'password',
await this.utilService.hashPass(dto.password),
);
return GenericRespEnum.PASS_UPDATED;
}
public async handleDiscordOauthPassW(
dto: SetOauthPassDto,
userId: string,
tok: string,
tokType: string,
) {
const user = await this.discordService.resolveUserByToken(tok, tokType);
if (!user) {
throw new UnauthorizedException();
}
this.logger.debug('Resolved Discord user', user);
const pfpUrl = this.discordService.resolvePfp(user.id, user.avatar);
this.logger.debug('Pfp url: ', pfpUrl);
const r = await this.usersService.create(
user.username,
dto.password,
user.email,
user.id,
false,
);
this.logger.debug('User creation finished, setting pfp');
await this.usersService.setUserPfp('DISCORD', {
user: user.id,
name: pfpUrl,
mime: undefined,
file: undefined,
});
return r;
}
public async handleGithubOauthPassW(
dto: SetOauthPassDto,
userId: string,
tok: string,
) {
const user = await this.githubService.fetchUser(tok);
if (!user) {
throw new UnauthorizedException();
}
const pfpUrl = user.avatar_url; // i love github api <3
this.logger.debug('Pfp url: ', pfpUrl);
const r = await this.usersService.create(
user.login,
dto.password,
await this.githubService.fetchUserMainEmail(tok),
userId,
false,
);
await this.usersService.setUserPfp('GITHUB', {
user: user.id.toString(),
name: pfpUrl,
mime: undefined,
file: undefined,
});
return r;
}
}