add device token

This commit is contained in:
2025-12-19 11:07:31 +03:30
parent 74e8480a68
commit 10178de7c1
10 changed files with 2078 additions and 0 deletions

243
src/DEVICE_TOKEN_API.md Normal file
View File

@@ -0,0 +1,243 @@
# API مدیریت توکن و تنظیمات دستگاه
این سند توضیح دهنده API های جدید اضافه شده برای مدیریت توکن و تنظیمات دستگاه است.
## تغییرات در مدل داده
### فیلدهای جدید در `DeviceSettings`
1. **UploadIntervalMin** (int): فاصله زمانی آپلود داده به دقیقه (پیش‌فرض: 5)
2. **DevicePhoneNumber** (string): شماره تلفن دستگاه
3. **SimCardType** (enum, nullable): نوع سیم‌کارت (همراه اول/ایرانسل/رایتل)
4. **TokenCode** (string, nullable): کد توکن 5 رقمی
5. **VerificationCode** (string, nullable): کد تایید 5 رقمی
6. **TokenExpiresAt** (DateTime, nullable): تاریخ انقضای توکن
### Enum نوع سیم‌کارت
```csharp
public enum SimCardType
{
Hamrahe_Aval = 1, // همراه اول
Irancell = 2, // ایرانسل
Rightel = 3 // رایتل
}
```
## API Endpoints
### 1. دریافت فاصله زمانی آپلود
**GET** `/api/DeviceToken/upload-interval`
دریافت مقدار `UPLOAD_INTERVAL_MIN` بر اساس شناسه دستگاه یا شماره تلفن.
#### پارامترها (Query String)
- `deviceId` (int, optional): شناسه دستگاه
- `devicePhoneNumber` (string, optional): شماره تلفن دستگاه
**نکته:** حداقل یکی از پارامترها باید ارسال شود.
#### مثال درخواست
```http
GET /api/DeviceToken/upload-interval?devicePhoneNumber=09123456789
```
#### پاسخ موفق
```json
{
"success": true,
"message": null,
"uploadIntervalMin": 5
}
```
#### پاسخ خطا
```json
{
"success": false,
"message": "دستگاه یافت نشد",
"uploadIntervalMin": null
}
```
---
### 2. درخواست توکن دستگاه
**POST** `/api/DeviceToken/request-token`
تولید کد توکن 5 رقمی و ارسال آن از طریق پیامک به شماره دستگاه.
#### بدنه درخواست (JSON)
```json
{
"devicePhoneNumber": "09123456789"
}
```
#### مثال درخواست
```http
POST /api/DeviceToken/request-token
Content-Type: application/json
{
"devicePhoneNumber": "09123456789"
}
```
#### پاسخ موفق
```json
{
"success": true,
"message": "کد تایید با موفقیت ارسال شد",
"tokenCode": "12345"
}
```
**نکته:** پیامک حاوی کد توکن به شماره مشخص شده ارسال می‌شود. کد دارای اعتبار 10 دقیقه است.
#### محاسبه کد تایید
کد تایید بر اساس فرمول زیر محاسبه می‌شود:
```
VerificationCode = (TokenCode × 7 + 12345) % 100000
```
---
### 3. تایید توکن دستگاه
**POST** `/api/DeviceToken/verify-token`
تایید کد تایید و ارسال تنظیمات کدشده دستگاه از طریق پیامک.
#### بدنه درخواست (JSON)
```json
{
"devicePhoneNumber": "09123456789",
"verificationCode": "98765"
}
```
#### مثال درخواست
```http
POST /api/DeviceToken/verify-token
Content-Type: application/json
{
"devicePhoneNumber": "09123456789",
"verificationCode": "98765"
}
```
#### پاسخ موفق
```json
{
"success": true,
"message": "تنظیمات با موفقیت ارسال شد",
"encodedSettings": "RGV2aWNlMDF8NQ=="
}
```
**نکته:** تنظیمات به صورت کدشده Base64 ارسال می‌شود. فرمت قبل از کدگذاری: `{DeviceName}|{UploadIntervalMin}`
#### پاسخ خطا
```json
{
"success": false,
"message": "کد تایید نادرست است",
"encodedSettings": null
}
```
---
### 4. بروزرسانی تنظیمات دستگاه
**PUT** `/api/DeviceSettings`
API موجود که حالا فیلدهای جدید را نیز پشتیبانی می‌کند.
#### بدنه درخواست (JSON)
```json
{
"id": 1,
"deviceId": 1,
"province": "تهران",
"city": "تهران",
"productType": "گلخانه",
"uploadIntervalMin": 5,
"devicePhoneNumber": "09123456789",
"simCardType": 1,
"minimumSmsIntervalMinutes": 15,
"minimumCallIntervalMinutes": 60
}
```
## فلوی کاری (Workflow)
### سناریو: دریافت تنظیمات دستگاه
1. **دستگاه درخواست توکن می‌کند:**
```http
POST /api/DeviceToken/request-token
Body: { "devicePhoneNumber": "09123456789" }
```
2. **سرور کد توکن تولید و ارسال می‌کند:**
- کد توکن 5 رقمی: مثلاً `12345`
- کد تایید محاسبه شده: `(12345 × 7 + 12345) % 100000 = 98760`
- پیامک حاوی کد توکن به شماره دستگاه ارسال می‌شود
3. **دستگاه کد تایید را محاسبه و ارسال می‌کند:**
```http
POST /api/DeviceToken/verify-token
Body: {
"devicePhoneNumber": "09123456789",
"verificationCode": "98760"
}
```
4. **سرور تنظیمات کدشده را ارسال می‌کند:**
- تنظیمات: `Device01|5`
- Base64: `RGV2aWNlMDF8NQ==`
- پیامک حاوی تنظیمات کدشده به شماره دستگاه ارسال می‌شود
5. **دستگاه تنظیمات را decode کرده و اعمال می‌کند**
## نکات امنیتی
1. کد توکن فقط 10 دقیقه اعتبار دارد
2. پس از تایید موفق، کدهای توکن و تایید از دیتابیس پاک می‌شوند
3. کدگذاری Base64 یک کدگذاری ساده است و برای امنیت بیشتر می‌توان از روش‌های پیچیده‌تر استفاده کرد
## Migration
Migration با نام `AddDeviceTokenAndPhoneFields` ایجاد و به دیتابیس اعمال شده است.
برای اعمال دستی (در صورت نیاز):
```bash
dotnet ef database update --project GreenHome.Infrastructure --startup-project GreenHome.Api
```
## تست API ها
می‌توانید از Swagger UI (که در حالت Development در `/scalar/v1` در دسترس است) برای تست API ها استفاده کنید.
یا از ابزارهایی مانند Postman/Insomnia با استفاده از نمونه‌های بالا.

View File

@@ -0,0 +1,128 @@
using GreenHome.Application;
using Microsoft.AspNetCore.Mvc;
namespace GreenHome.Api.Controllers;
/// <summary>
/// کنترلر مدیریت توکن و تنظیمات دستگاه
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class DeviceTokenController : ControllerBase
{
private readonly IDeviceTokenService deviceTokenService;
private readonly ILogger<DeviceTokenController> logger;
public DeviceTokenController(
IDeviceTokenService deviceTokenService,
ILogger<DeviceTokenController> logger)
{
this.deviceTokenService = deviceTokenService;
this.logger = logger;
}
/// <summary>
/// دریافت فاصله زمانی آپلود دستگاه
/// </summary>
/// <param name="deviceId">شناسه دستگاه (اختیاری)</param>
/// <param name="devicePhoneNumber">شماره تلفن دستگاه (اختیاری)</param>
/// <returns>فاصله زمانی آپلود به دقیقه</returns>
[HttpGet("upload-interval")]
public async Task<ActionResult<GetUploadIntervalResponse>> GetUploadInterval(
[FromQuery] int? deviceId,
[FromQuery] string? devicePhoneNumber,
CancellationToken cancellationToken)
{
if (!deviceId.HasValue && string.IsNullOrWhiteSpace(devicePhoneNumber))
{
return BadRequest(new GetUploadIntervalResponse
{
Success = false,
Message = "حداقل یکی از پارامترهای deviceId یا devicePhoneNumber باید ارسال شود"
});
}
var request = new GetUploadIntervalRequest
{
DeviceId = deviceId,
DevicePhoneNumber = devicePhoneNumber
};
var result = await deviceTokenService.GetUploadIntervalAsync(request, cancellationToken);
if (!result.Success)
{
return NotFound(result);
}
return Ok(result);
}
/// <summary>
/// درخواست توکن دستگاه (تولید و ارسال کد از طریق پیامک)
/// </summary>
/// <param name="request">درخواست شامل شماره تلفن دستگاه</param>
/// <returns>نتیجه درخواست</returns>
[HttpPost("request-token")]
public async Task<ActionResult<RequestDeviceTokenResponse>> RequestToken(
[FromBody] RequestDeviceTokenRequest request,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(request.DevicePhoneNumber))
{
return BadRequest(new RequestDeviceTokenResponse
{
Success = false,
Message = "شماره تلفن دستگاه الزامی است"
});
}
var result = await deviceTokenService.RequestDeviceTokenAsync(request, cancellationToken);
if (!result.Success)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// تایید توکن دستگاه (ارسال تنظیمات کدشده از طریق پیامک)
/// </summary>
/// <param name="request">درخواست شامل شماره تلفن و کد تایید</param>
/// <returns>نتیجه تایید و تنظیمات کدشده</returns>
[HttpPost("verify-token")]
public async Task<ActionResult<VerifyDeviceTokenResponse>> VerifyToken(
[FromBody] VerifyDeviceTokenRequest request,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(request.DevicePhoneNumber))
{
return BadRequest(new VerifyDeviceTokenResponse
{
Success = false,
Message = "شماره تلفن دستگاه الزامی است"
});
}
if (string.IsNullOrWhiteSpace(request.VerificationCode))
{
return BadRequest(new VerifyDeviceTokenResponse
{
Success = false,
Message = "کد تایید الزامی است"
});
}
var result = await deviceTokenService.VerifyDeviceTokenAsync(request, cancellationToken);
if (!result.Success)
{
return BadRequest(result);
}
return Ok(result);
}
}

View File

@@ -66,6 +66,7 @@ builder.Services.AddScoped<GreenHome.Application.IUserDailyReportService, GreenH
builder.Services.AddScoped<GreenHome.Application.IChecklistService, GreenHome.Infrastructure.ChecklistService>(); builder.Services.AddScoped<GreenHome.Application.IChecklistService, GreenHome.Infrastructure.ChecklistService>();
builder.Services.AddScoped<GreenHome.Application.IMonthlyReportService, GreenHome.Infrastructure.MonthlyReportService>(); builder.Services.AddScoped<GreenHome.Application.IMonthlyReportService, GreenHome.Infrastructure.MonthlyReportService>();
builder.Services.AddScoped<GreenHome.Application.IDevicePostService, GreenHome.Infrastructure.DevicePostService>(); builder.Services.AddScoped<GreenHome.Application.IDevicePostService, GreenHome.Infrastructure.DevicePostService>();
builder.Services.AddScoped<GreenHome.Application.IDeviceTokenService, GreenHome.Infrastructure.DeviceTokenService>();
// SMS Service Configuration // SMS Service Configuration
builder.Services.AddIppanelSms(builder.Configuration); builder.Services.AddIppanelSms(builder.Configuration);

View File

@@ -128,6 +128,13 @@ public sealed class DeviceSettingsDto
public int MinimumCallIntervalMinutes { get; set; } = 60; public int MinimumCallIntervalMinutes { get; set; } = 60;
public decimal? AreaSquareMeters { get; set; } public decimal? AreaSquareMeters { get; set; }
public int UploadIntervalMin { get; set; } = 5;
public string DevicePhoneNumber { get; set; } = string.Empty;
public Domain.SimCardType? SimCardType { get; set; }
public string? TokenCode { get; set; }
public string? VerificationCode { get; set; }
public DateTime? TokenExpiresAt { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; } public DateTime UpdatedAt { get; set; }
} }
@@ -312,4 +319,62 @@ public sealed class UserDailyReportFilter
public int? Month { get; set; } public int? Month { get; set; }
public int Page { get; set; } = 1; public int Page { get; set; } = 1;
public int PageSize { get; set; } = 20; public int PageSize { get; set; } = 20;
}
// DTOs برای مدیریت توکن دستگاه
/// <summary>
/// درخواست دریافت فاصله زمانی آپلود
/// </summary>
public sealed class GetUploadIntervalRequest
{
public int? DeviceId { get; set; }
public string? DevicePhoneNumber { get; set; }
}
/// <summary>
/// پاسخ دریافت فاصله زمانی آپلود
/// </summary>
public sealed class GetUploadIntervalResponse
{
public bool Success { get; set; }
public string? Message { get; set; }
public int? UploadIntervalMin { get; set; }
}
/// <summary>
/// درخواست دریافت توکن دستگاه
/// </summary>
public sealed class RequestDeviceTokenRequest
{
public required string DevicePhoneNumber { get; set; }
}
/// <summary>
/// پاسخ دریافت توکن دستگاه
/// </summary>
public sealed class RequestDeviceTokenResponse
{
public bool Success { get; set; }
public string? Message { get; set; }
public string? TokenCode { get; set; }
}
/// <summary>
/// درخواست تایید توکن دستگاه
/// </summary>
public sealed class VerifyDeviceTokenRequest
{
public required string DevicePhoneNumber { get; set; }
public required string VerificationCode { get; set; }
}
/// <summary>
/// پاسخ تایید توکن دستگاه
/// </summary>
public sealed class VerifyDeviceTokenResponse
{
public bool Success { get; set; }
public string? Message { get; set; }
public string? EncodedSettings { get; set; }
} }

View File

@@ -0,0 +1,23 @@
namespace GreenHome.Application;
/// <summary>
/// سرویس مدیریت توکن و تنظیمات دستگاه
/// </summary>
public interface IDeviceTokenService
{
/// <summary>
/// دریافت فاصله زمانی آپلود بر اساس شماره تلفن یا شناسه دستگاه
/// </summary>
Task<GetUploadIntervalResponse> GetUploadIntervalAsync(GetUploadIntervalRequest request, CancellationToken cancellationToken);
/// <summary>
/// درخواست توکن دستگاه (تولید و ارسال کد)
/// </summary>
Task<RequestDeviceTokenResponse> RequestDeviceTokenAsync(RequestDeviceTokenRequest request, CancellationToken cancellationToken);
/// <summary>
/// تایید توکن دستگاه (ارسال تنظیمات)
/// </summary>
Task<VerifyDeviceTokenResponse> VerifyDeviceTokenAsync(VerifyDeviceTokenRequest request, CancellationToken cancellationToken);
}

View File

@@ -1,5 +1,26 @@
namespace GreenHome.Domain; namespace GreenHome.Domain;
/// <summary>
/// نوع سیم کارت
/// </summary>
public enum SimCardType
{
/// <summary>
/// همراه اول
/// </summary>
Hamrahe_Aval = 1,
/// <summary>
/// ایرانسل
/// </summary>
Irancell = 2,
/// <summary>
/// رایتل
/// </summary>
Rightel = 3
}
public sealed class DeviceSettings public sealed class DeviceSettings
{ {
public int Id { get; set; } public int Id { get; set; }
@@ -46,6 +67,36 @@ public sealed class DeviceSettings
/// </summary> /// </summary>
public decimal? AreaSquareMeters { get; set; } public decimal? AreaSquareMeters { get; set; }
/// <summary>
/// فاصله زمانی آپلود داده (به دقیقه)
/// </summary>
public int UploadIntervalMin { get; set; } = 5;
/// <summary>
/// شماره تلفن دستگاه
/// </summary>
public string DevicePhoneNumber { get; set; } = string.Empty;
/// <summary>
/// نوع سیم کارت
/// </summary>
public SimCardType? SimCardType { get; set; }
/// <summary>
/// کد توکن (5 رقمی)
/// </summary>
public string? TokenCode { get; set; }
/// <summary>
/// کد تایید (5 رقمی)
/// </summary>
public string? VerificationCode { get; set; }
/// <summary>
/// تاریخ انقضای توکن
/// </summary>
public DateTime? TokenExpiresAt { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; } public DateTime UpdatedAt { get; set; }
} }

View File

@@ -0,0 +1,249 @@
using GreenHome.Application;
using GreenHome.Sms.Ippanel;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace GreenHome.Infrastructure;
/// <summary>
/// سرویس مدیریت توکن و تنظیمات دستگاه
/// </summary>
public sealed class DeviceTokenService : IDeviceTokenService
{
private readonly GreenHomeDbContext dbContext;
private readonly ISmsService smsService;
private readonly ILogger<DeviceTokenService> logger;
public DeviceTokenService(
GreenHomeDbContext dbContext,
ISmsService smsService,
ILogger<DeviceTokenService> logger)
{
this.dbContext = dbContext;
this.smsService = smsService;
this.logger = logger;
}
/// <summary>
/// دریافت فاصله زمانی آپلود بر اساس شماره تلفن یا شناسه دستگاه
/// </summary>
public async Task<GetUploadIntervalResponse> GetUploadIntervalAsync(
GetUploadIntervalRequest request,
CancellationToken cancellationToken)
{
try
{
Domain.DeviceSettings? settings = null;
// جستجو بر اساس DeviceId یا DevicePhoneNumber
if (request.DeviceId.HasValue)
{
settings = await dbContext.DeviceSettings
.AsNoTracking()
.FirstOrDefaultAsync(ds => ds.DeviceId == request.DeviceId.Value, cancellationToken);
}
else if (!string.IsNullOrWhiteSpace(request.DevicePhoneNumber))
{
settings = await dbContext.DeviceSettings
.AsNoTracking()
.FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken);
}
if (settings == null)
{
return new GetUploadIntervalResponse
{
Success = false,
Message = "دستگاه یافت نشد"
};
}
return new GetUploadIntervalResponse
{
Success = true,
UploadIntervalMin = settings.UploadIntervalMin
};
}
catch (Exception ex)
{
logger.LogError(ex, "Error getting upload interval for device");
return new GetUploadIntervalResponse
{
Success = false,
Message = "خطا در دریافت اطلاعات"
};
}
}
/// <summary>
/// درخواست توکن دستگاه (تولید و ارسال کد)
/// </summary>
public async Task<RequestDeviceTokenResponse> RequestDeviceTokenAsync(
RequestDeviceTokenRequest request,
CancellationToken cancellationToken)
{
try
{
// پیدا کردن تنظیمات دستگاه بر اساس شماره تلفن
var settings = await dbContext.DeviceSettings
.FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken);
if (settings == null)
{
return new RequestDeviceTokenResponse
{
Success = false,
Message = "دستگاه با این شماره تلفن یافت نشد"
};
}
// تولید کد توکن 5 رقمی
var random = new Random();
var tokenCode = random.Next(10000, 99999).ToString();
// تولید کد تایید بر اساس فرمول: (TokenCode * 7 + 12345) % 100000
var verificationCode = ((int.Parse(tokenCode) * 7 + 12345) % 100000).ToString("D5");
// ذخیره کدها
settings.TokenCode = tokenCode;
settings.VerificationCode = verificationCode;
settings.TokenExpiresAt = DateTime.UtcNow.AddMinutes(10); // اعتبار 10 دقیقه
settings.UpdatedAt = DateTime.UtcNow;
await dbContext.SaveChangesAsync(cancellationToken);
// ارسال کد توکن از طریق پیامک
try
{
await smsService.SendWebserviceSmsAsync(new WebserviceSmsRequest
{
Recipient = request.DevicePhoneNumber,
Message = $"کد تایید دستگاه شما: {tokenCode}\nاعتبار: 10 دقیقه"
}, cancellationToken);
}
catch (Exception smsEx)
{
logger.LogError(smsEx, "Error sending token SMS to {PhoneNumber}", request.DevicePhoneNumber);
return new RequestDeviceTokenResponse
{
Success = false,
Message = "خطا در ارسال پیامک"
};
}
logger.LogInformation("Token requested for device phone {PhoneNumber}", request.DevicePhoneNumber);
return new RequestDeviceTokenResponse
{
Success = true,
Message = "کد تایید با موفقیت ارسال شد",
TokenCode = tokenCode
};
}
catch (Exception ex)
{
logger.LogError(ex, "Error requesting device token");
return new RequestDeviceTokenResponse
{
Success = false,
Message = "خطا در درخواست توکن"
};
}
}
/// <summary>
/// تایید توکن دستگاه (ارسال تنظیمات)
/// </summary>
public async Task<VerifyDeviceTokenResponse> VerifyDeviceTokenAsync(
VerifyDeviceTokenRequest request,
CancellationToken cancellationToken)
{
try
{
// پیدا کردن تنظیمات دستگاه
var settings = await dbContext.DeviceSettings
.Include(ds => ds.Device)
.FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken);
if (settings == null)
{
return new VerifyDeviceTokenResponse
{
Success = false,
Message = "دستگاه با این شماره تلفن یافت نشد"
};
}
// بررسی انقضای توکن
if (settings.TokenExpiresAt == null || settings.TokenExpiresAt < DateTime.UtcNow)
{
return new VerifyDeviceTokenResponse
{
Success = false,
Message = "کد تایید منقضی شده است"
};
}
// بررسی کد تایید
if (settings.VerificationCode != request.VerificationCode)
{
return new VerifyDeviceTokenResponse
{
Success = false,
Message = "کد تایید نادرست است"
};
}
// رمزگذاری ساده تنظیمات: DeviceName|UploadIntervalMin به Base64
var deviceName = settings.Device.DeviceName;
var uploadInterval = settings.UploadIntervalMin;
var plainText = $"{deviceName}|{uploadInterval}";
var encodedSettings = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(plainText));
// ارسال تنظیمات کدشده از طریق پیامک
try
{
await smsService.SendWebserviceSmsAsync(new WebserviceSmsRequest
{
Recipient = request.DevicePhoneNumber,
Message = $"تنظیمات دستگاه:\n{encodedSettings}"
}, cancellationToken);
}
catch (Exception smsEx)
{
logger.LogError(smsEx, "Error sending settings SMS to {PhoneNumber}", request.DevicePhoneNumber);
return new VerifyDeviceTokenResponse
{
Success = false,
Message = "خطا در ارسال پیامک"
};
}
// پاک کردن کدها بعد از استفاده موفق
settings.TokenCode = null;
settings.VerificationCode = null;
settings.TokenExpiresAt = null;
settings.UpdatedAt = DateTime.UtcNow;
await dbContext.SaveChangesAsync(cancellationToken);
logger.LogInformation("Device token verified for {PhoneNumber}", request.DevicePhoneNumber);
return new VerifyDeviceTokenResponse
{
Success = true,
Message = "تنظیمات با موفقیت ارسال شد",
EncodedSettings = encodedSettings
};
}
catch (Exception ex)
{
logger.LogError(ex, "Error verifying device token");
return new VerifyDeviceTokenResponse
{
Success = false,
Message = "خطا در تایید توکن"
};
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GreenHome.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddDeviceTokenAndPhoneFields : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "DevicePhoneNumber",
table: "DeviceSettings",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<int>(
name: "SimCardType",
table: "DeviceSettings",
type: "int",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "TokenCode",
table: "DeviceSettings",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "TokenExpiresAt",
table: "DeviceSettings",
type: "datetime2",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "UploadIntervalMin",
table: "DeviceSettings",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "VerificationCode",
table: "DeviceSettings",
type: "nvarchar(max)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DevicePhoneNumber",
table: "DeviceSettings");
migrationBuilder.DropColumn(
name: "SimCardType",
table: "DeviceSettings");
migrationBuilder.DropColumn(
name: "TokenCode",
table: "DeviceSettings");
migrationBuilder.DropColumn(
name: "TokenExpiresAt",
table: "DeviceSettings");
migrationBuilder.DropColumn(
name: "UploadIntervalMin",
table: "DeviceSettings");
migrationBuilder.DropColumn(
name: "VerificationCode",
table: "DeviceSettings");
}
}
}

View File

@@ -590,6 +590,10 @@ namespace GreenHome.Infrastructure.Migrations
b.Property<int>("DeviceId") b.Property<int>("DeviceId")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("DevicePhoneNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<decimal?>("Latitude") b.Property<decimal?>("Latitude")
.HasColumnType("decimal(9,6)"); .HasColumnType("decimal(9,6)");
@@ -616,9 +620,24 @@ namespace GreenHome.Infrastructure.Migrations
.HasMaxLength(100) .HasMaxLength(100)
.HasColumnType("nvarchar(100)"); .HasColumnType("nvarchar(100)");
b.Property<int?>("SimCardType")
.HasColumnType("int");
b.Property<string>("TokenCode")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("TokenExpiresAt")
.HasColumnType("datetime2");
b.Property<DateTime>("UpdatedAt") b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime2"); .HasColumnType("datetime2");
b.Property<int>("UploadIntervalMin")
.HasColumnType("int");
b.Property<string>("VerificationCode")
.HasColumnType("nvarchar(max)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("DeviceId") b.HasIndex("DeviceId")