mirror of
https://github.com/SyncrowIOT/backend.git
synced 2026-10-23 10:47:54 +00:00
user list api done
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import config from './config';
|
||||
import { AuthenticationModule } from './modules/authentication/authentication.module';
|
||||
import { AuthenticationController } from './modules/authentication/controllers/authentication.controller';
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [AuthController],
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
load: config,
|
||||
}),
|
||||
AuthenticationModule,
|
||||
],
|
||||
controllers: [AuthController,AuthenticationController],
|
||||
providers: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs(
|
||||
'auth-config',
|
||||
(): Record<string, any> => ({
|
||||
DEVICE_ID: process.env.DEVICE_ID,
|
||||
ACCESS_KEY: process.env.ACCESS_KEY,
|
||||
SECRET_KEY: process.env.SECRET_KEY,
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
import AuthConfig from './auth.config';
|
||||
|
||||
export default [AuthConfig];
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthenticationController } from './controllers/authentication.controller';
|
||||
import { AuthenticationService } from './services/authentication.service';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule],
|
||||
controllers: [AuthenticationController],
|
||||
providers: [AuthenticationService],
|
||||
exports: [AuthenticationService],
|
||||
})
|
||||
export class AuthenticationModule {}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Controller, Post } from '@nestjs/common';
|
||||
import { AuthenticationService } from '../services/authentication.service';
|
||||
|
||||
@Controller({
|
||||
version: '1',
|
||||
path: 'authentication',
|
||||
})
|
||||
export class AuthenticationController {
|
||||
constructor(private readonly authenticationService: AuthenticationService) {}
|
||||
@Post('auth')
|
||||
async Authentication() {
|
||||
return await this.authenticationService.main();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import * as qs from 'qs';
|
||||
import * as crypto from 'crypto';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import axios from 'axios';
|
||||
@Injectable()
|
||||
export class AuthenticationService {
|
||||
private token: string;
|
||||
private deviceId: string;
|
||||
private accessKey: string;
|
||||
private secretKey: string;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
(this.deviceId = this.configService.get<string>('auth-config.DEVICE_ID')),
|
||||
(this.accessKey = this.configService.get<string>(
|
||||
'auth-config.ACCESS_KEY',
|
||||
)),
|
||||
(this.secretKey = this.configService.get<string>(
|
||||
'auth-config.SECRET_KEY',
|
||||
));
|
||||
}
|
||||
|
||||
async main() {
|
||||
await this.getToken();
|
||||
const data = await this.getDeviceInfo(this.deviceId);
|
||||
console.log('fetch success: ', JSON.stringify(data));
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
|
||||
async getToken() {
|
||||
const method = 'GET';
|
||||
const timestamp = Date.now().toString();
|
||||
const signUrl = 'https://openapi.tuyaeu.com/v1.0/token?grant_type=1';
|
||||
const contentHash = crypto.createHash('sha256').update('').digest('hex');
|
||||
const stringToSign = [method, contentHash, '', signUrl].join('\n');
|
||||
const signStr = this.accessKey + timestamp + stringToSign;
|
||||
|
||||
const headers = {
|
||||
t: timestamp,
|
||||
sign_method: 'HMAC-SHA256',
|
||||
client_id: this.accessKey,
|
||||
sign: await this.encryptStr(signStr, this.secretKey),
|
||||
};
|
||||
|
||||
const { data: login } = await axios.get(
|
||||
'https://openapi.tuyaeu.com/v1.0/token',
|
||||
{
|
||||
params: {
|
||||
grant_type: 1,
|
||||
},
|
||||
headers,
|
||||
},
|
||||
);
|
||||
|
||||
if (!login || !login.success) {
|
||||
throw new Error(`fetch failed: ${login.msg}`);
|
||||
}
|
||||
this.token = login.result.access_token;
|
||||
}
|
||||
|
||||
async getDeviceInfo(deviceId: string) {
|
||||
const query = {};
|
||||
const method = 'POST';
|
||||
const url = `https://openapi.tuyaeu.com/v1.0/devices/${deviceId}/commands`;
|
||||
const reqHeaders: { [k: string]: string } = await this.getRequestSign(
|
||||
url,
|
||||
method,
|
||||
{},
|
||||
query,
|
||||
);
|
||||
|
||||
const { data } = await axios.post(url, {}, reqHeaders);
|
||||
|
||||
if (!data || !data.success) {
|
||||
throw new Error(`request api failed: ${data.msg}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async encryptStr(str: string, secret: string): Promise<string> {
|
||||
return crypto
|
||||
.createHmac('sha256', secret)
|
||||
.update(str, 'utf8')
|
||||
.digest('hex')
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
async getRequestSign(
|
||||
path: string,
|
||||
method: string,
|
||||
headers: { [k: string]: string } = {},
|
||||
query: { [k: string]: any } = {},
|
||||
body: { [k: string]: any } = {},
|
||||
) {
|
||||
const t = Date.now().toString();
|
||||
const [uri, pathQuery] = path.split('?');
|
||||
const queryMerged = Object.assign(query, qs.parse(pathQuery));
|
||||
const sortedQuery: { [k: string]: string } = {};
|
||||
Object.keys(queryMerged)
|
||||
.sort()
|
||||
.forEach((i) => (sortedQuery[i] = query[i]));
|
||||
|
||||
const querystring = decodeURIComponent(qs.stringify(sortedQuery));
|
||||
const url = querystring ? `${uri}?${querystring}` : uri;
|
||||
const contentHash = crypto
|
||||
.createHash('sha256')
|
||||
.update(JSON.stringify(body))
|
||||
.digest('hex');
|
||||
const stringToSign = [method, contentHash, '', url].join('\n');
|
||||
const signStr = this.accessKey + this.token + t + stringToSign;
|
||||
return {
|
||||
t,
|
||||
path: url,
|
||||
client_id: this.accessKey,
|
||||
sign: await this.encryptStr(signStr, this.secretKey),
|
||||
sign_method: 'HMAC-SHA256',
|
||||
access_token: this.token,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
describe('AppController', () => {
|
||||
let appController: AppController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const app: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
}).compile();
|
||||
|
||||
appController = app.get<AppController>(AppController);
|
||||
});
|
||||
|
||||
describe('root', () => {
|
||||
it('should return "Hello World!"', () => {
|
||||
expect(appController.getHello()).toBe('Hello World!');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { AppService } from './backend.service';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
||||
@Get()
|
||||
@Get('healthcheck')
|
||||
getHello(): string {
|
||||
return this.appService.getHello();
|
||||
return this.appService.healthcheck();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './backend.controller';
|
||||
import { AppService } from './backend.service';
|
||||
import { UserModule } from './modules/user/user.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import config from './config';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
load: config,
|
||||
}),
|
||||
UserModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class BackendModule {}
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
healthcheck(): string {
|
||||
return 'Healthcheck!';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs(
|
||||
'auth-config',
|
||||
(): Record<string, any> => ({
|
||||
//DEVICE_ID: process.env.DEVICE_ID,
|
||||
ACCESS_KEY: process.env.ACCESS_KEY,
|
||||
SECRET_KEY: process.env.SECRET_KEY,
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
import AuthConfig from './auth.config';
|
||||
|
||||
export default [AuthConfig];
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { BackendModule } from './backend.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(BackendModule);
|
||||
await app.listen(6000);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Controller, Get, Query } from '@nestjs/common';
|
||||
import { UserService } from '../services/user.service';
|
||||
import { UserListDto } from '../dtos/user.list.dto';
|
||||
|
||||
//@ApiTags('User Module')
|
||||
@Controller({
|
||||
version: '1',
|
||||
path: 'user',
|
||||
})
|
||||
export class UserController {
|
||||
constructor(private readonly userService: UserService) {}
|
||||
|
||||
@Get('list')
|
||||
async userList(@Query() userListDto: UserListDto) {
|
||||
try {
|
||||
return await this.userService.userDetails(userListDto);
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class UserListDto {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
schema: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
page_no: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
page_size: number;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
username: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
start_time: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
end_time: number;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||
import { UserListDto } from '../dtos/user.list.dto';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
private accessKey: string;
|
||||
private secretKey: string;
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
(this.accessKey = this.configService.get<string>('auth-config.ACCESS_KEY')),
|
||||
(this.secretKey = this.configService.get<string>(
|
||||
'auth-config.SECRET_KEY',
|
||||
));
|
||||
}
|
||||
async userDetails(userListDto: UserListDto) {
|
||||
const url = `https://openapi.tuyaeu.com/v2.0/apps/${userListDto.schema}/users`;
|
||||
|
||||
const tuya = new TuyaContext({
|
||||
baseUrl: 'https://openapi.tuyacn.com',
|
||||
accessKey:this.secretKey,
|
||||
secretKey:this.accessKey,
|
||||
});
|
||||
|
||||
const data = await tuya.request({
|
||||
method: 'GET',
|
||||
path: url,
|
||||
query: userListDto,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UserService } from './services/user.service';
|
||||
import { UserController } from './controllers/user.controller';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule],
|
||||
controllers: [UserController],
|
||||
providers: [UserService],
|
||||
exports: [UserService],
|
||||
})
|
||||
export class UserModule {}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from './../src/app.module';
|
||||
|
||||
describe('AppController (e2e)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleFixture.createNestApplication();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('/ (GET)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.expect(200)
|
||||
.expect('Hello World!');
|
||||
});
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"rootDir": ".",
|
||||
"testEnvironment": "node",
|
||||
"testRegex": ".e2e-spec.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user