impl Account Table
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import Fluent
|
|
||||||
import Vapor
|
import Vapor
|
||||||
|
|
||||||
struct InfodeskController: RouteCollection {
|
struct InfodeskController: RouteCollection {
|
||||||
|
160
Sources/stella/Controllers/OpenApi/AuthController.swift
Normal file
160
Sources/stella/Controllers/OpenApi/AuthController.swift
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
import Vapor
|
||||||
|
import Fluent
|
||||||
|
|
||||||
|
struct AuthController: RouteCollection {
|
||||||
|
func boot(routes: any RoutesBuilder) throws {
|
||||||
|
routes.post("v4", "device", "accessToken", "create", use: self.createAccessToken)
|
||||||
|
routes.post("v3", "agreement", "getForLogin", use: self.loginAgreement)
|
||||||
|
routes.post("v4", "auth", "loginDevice", use: self.loginDevice)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func createAccessToken(req: Request) async throws -> AccessTokenRes {
|
||||||
|
AccessTokenRes(
|
||||||
|
accessToken: "fwPla7fQ8ty9+DZT/lD//uWZD4uD6C4lD6gGIIZTLKRTQ52/SLCRmk/370jcWGs+e+1iSoZtL7lj8ov9B0/jHmijH4nsHPQT6pchaQM1M9mtwYNQq0BWhVr9hF0jjCK/a5LIVd1kBac/Gemv29WKEDKSrUS9HxxUigoPRwtOy8m+oDj9FmDJZ+rzqWCc0QjES4Ky0fTpXZ7ESoguDzNmRtW3FYr+OFexw8wBPlwiC4w=",
|
||||||
|
expiryTime: Int(Date.init(timeIntervalSinceNow: .init(0)).timeIntervalSince1970)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func loginAgreement(req: Request) async throws -> String {
|
||||||
|
let body = try req.content.decode(LoginAgreementReq.self, as: .json)
|
||||||
|
|
||||||
|
return #"""
|
||||||
|
{
|
||||||
|
"adAgreementStatus": "n",
|
||||||
|
"agreement": {
|
||||||
|
"E001": "n",
|
||||||
|
"E002": "n",
|
||||||
|
"E006": "n",
|
||||||
|
"N002": "n",
|
||||||
|
"N003": "n",
|
||||||
|
"timestamp": "\#(Int(Date().timeIntervalSince1970) * 1000)"
|
||||||
|
},
|
||||||
|
"agreementPopup": "n",
|
||||||
|
"appId": "\#(body.appId)",
|
||||||
|
"appName": "World Flipper (NA)",
|
||||||
|
"context": "login",
|
||||||
|
"country": "\#(body.country)",
|
||||||
|
"firstAgreement": "n",
|
||||||
|
"idpCode": "\#(body.idpCode)",
|
||||||
|
"idpId": "6076008646",
|
||||||
|
"informationSecurityCountry": "kr",
|
||||||
|
"kakaoSyncAgreementGetSet": "n",
|
||||||
|
"kakaoSyncStatus": "off",
|
||||||
|
"kakaogameSdkVer": "3.0",
|
||||||
|
"lang": "\#(body.lang)",
|
||||||
|
"partnerId": 825,
|
||||||
|
"partnerName": "주식회사 카카오게임즈",
|
||||||
|
"plusFriendStatusInfo": null,
|
||||||
|
"policyApplyTime": 1630854000000
|
||||||
|
}
|
||||||
|
"""#
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func loginDevice(req: Request) async throws -> Response {
|
||||||
|
let body = try req.content.decode(LoginDeviceReq.self, as: .json)
|
||||||
|
|
||||||
|
let idpAlias = generateIdpAlias(appId: body.appId, deviceId: body.deviceId, serialNo: body.serialNo)
|
||||||
|
let idpId = body.whiteKey
|
||||||
|
var account: Account? = nil
|
||||||
|
|
||||||
|
if let rawAccountId = req.headers["playerId"].first, let accountId = Int(rawAccountId) {
|
||||||
|
if let existingAccount = try await Account.query(on: req.db).filter(\.$id == accountId).first() {
|
||||||
|
account = existingAccount
|
||||||
|
}
|
||||||
|
} else if let existingAccount = try await Account.query(on: req.db).filter(\.$idpId == idpId).first() {
|
||||||
|
account = existingAccount
|
||||||
|
} else {
|
||||||
|
let account = Account(appId: body.appId, idpAlias: idpAlias, idpCode: "zd3", idpId: idpId, status: "normal")
|
||||||
|
try await account.create(on: req.db)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let account = account else {
|
||||||
|
return Response(status: .badRequest, body: "{\"error\": \"Bad Request\", \"message\": \"Invalid playerId provided.\"}")
|
||||||
|
}
|
||||||
|
return Response(status: .notImplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccessTokenRes: Content {
|
||||||
|
let accessToken: String
|
||||||
|
let expiryTime: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoginAgreementReq: Content {
|
||||||
|
let deviceId: String
|
||||||
|
let os: String
|
||||||
|
let country: String
|
||||||
|
let lang: String
|
||||||
|
let appId: String
|
||||||
|
let idpCode: String
|
||||||
|
let serialNo: String
|
||||||
|
let idpId: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoginDeviceReq: Content {
|
||||||
|
let lang: String
|
||||||
|
let clientTime: Int
|
||||||
|
let deviceId: String
|
||||||
|
let serialNo: String
|
||||||
|
let country: String
|
||||||
|
let whiteKey: String
|
||||||
|
let market: String
|
||||||
|
let appSecret: String
|
||||||
|
let deviceAppKey: String
|
||||||
|
let sdkVer: String
|
||||||
|
let appVer: String
|
||||||
|
let os: String
|
||||||
|
let loginType: String
|
||||||
|
let accessToken: String
|
||||||
|
let resume: Bool
|
||||||
|
let osVer: String
|
||||||
|
let appId: String
|
||||||
|
let deviceModel: String
|
||||||
|
let network: String
|
||||||
|
let isIosAppOnMac: Bool
|
||||||
|
let adid: String
|
||||||
|
let timezoneOffset: Int
|
||||||
|
let fields: [String]
|
||||||
|
let telecom: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoginDeviceRes: Content {
|
||||||
|
let zatExpiryTime: Int
|
||||||
|
let zrtExpiryTime: Int
|
||||||
|
let firstLogin: Bool
|
||||||
|
let externalToken: String
|
||||||
|
let zat: String
|
||||||
|
let zrt: String
|
||||||
|
let player: Player
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Player: Content {
|
||||||
|
let idpId: String
|
||||||
|
let appId: String
|
||||||
|
let lang: String
|
||||||
|
let playerId: String
|
||||||
|
let agreement: AgreementResponse
|
||||||
|
let pushOption: PushOptionResponse
|
||||||
|
let lastLoginTime: Int
|
||||||
|
let regTime: Int
|
||||||
|
let idpAlias: String
|
||||||
|
let firstLoginTime: Int
|
||||||
|
let status: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AgreementResponse: Content {
|
||||||
|
let E001: String
|
||||||
|
let E002: String
|
||||||
|
let E006: String
|
||||||
|
let N002: String
|
||||||
|
let N003: String
|
||||||
|
let timestamp: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PushOptionResponse: Content {
|
||||||
|
let night: String
|
||||||
|
let player: String
|
||||||
|
}
|
14
Sources/stella/Controllers/OpenApi/UtilController.swift
Normal file
14
Sources/stella/Controllers/OpenApi/UtilController.swift
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct UtilController: RouteCollection {
|
||||||
|
func boot(routes: any RoutesBuilder) throws {
|
||||||
|
let group = routes.grouped("v3", "util")
|
||||||
|
|
||||||
|
group.post("country", "get", use: self.getCountry)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sendable
|
||||||
|
func getCountry(req: Request) async throws -> String {
|
||||||
|
"{\"country\": \"us\"}"
|
||||||
|
}
|
||||||
|
}
|
14
Sources/stella/Controllers/OpenApiController.swift
Normal file
14
Sources/stella/Controllers/OpenApiController.swift
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import Vapor
|
||||||
|
|
||||||
|
struct OpenApiController: RouteCollection {
|
||||||
|
func boot(routes: any RoutesBuilder) throws {
|
||||||
|
let group = routes.grouped("openapi", "service")
|
||||||
|
try group.register(collection: UtilController())
|
||||||
|
try group.register(collection: AuthController())
|
||||||
|
|
||||||
|
group.post("v3", "log", "writeSdkBasicLog") { req in
|
||||||
|
req.logger.log(level: .debug, .init(stringLiteral: req.body.string ?? ""))
|
||||||
|
return Response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,17 +0,0 @@
|
|||||||
import Fluent
|
|
||||||
import Vapor
|
|
||||||
|
|
||||||
struct TodoDTO: Content {
|
|
||||||
var id: UUID?
|
|
||||||
var title: String?
|
|
||||||
|
|
||||||
func toModel() -> Todo {
|
|
||||||
let model = Todo()
|
|
||||||
|
|
||||||
model.id = self.id
|
|
||||||
if let title = self.title {
|
|
||||||
model.title = title
|
|
||||||
}
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
}
|
|
21
Sources/stella/Migrations/CreateAccount.swift
Normal file
21
Sources/stella/Migrations/CreateAccount.swift
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import Fluent
|
||||||
|
|
||||||
|
struct CreateAccount: AsyncMigration {
|
||||||
|
func prepare(on database: any Database) async throws {
|
||||||
|
try await database.schema("accounts")
|
||||||
|
.field("id", .int, .identifier(auto: true))
|
||||||
|
.field("app_id", .string, .required)
|
||||||
|
.field("first_login_time", .date, .required)
|
||||||
|
.field("idp_alias", .string, .required)
|
||||||
|
.field("idp_code", .string, .required)
|
||||||
|
.field("idp_id", .string, .required)
|
||||||
|
.field("reg_time", .date, .required)
|
||||||
|
.field("last_login_time", .date, .required)
|
||||||
|
.field("status", .string, .required)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
func revert(on database: any Database) async throws {
|
||||||
|
try await database.schema("accounts").delete()
|
||||||
|
}
|
||||||
|
}
|
@@ -1,14 +0,0 @@
|
|||||||
import Fluent
|
|
||||||
|
|
||||||
struct CreateTodo: AsyncMigration {
|
|
||||||
func prepare(on database: any Database) async throws {
|
|
||||||
try await database.schema("todos")
|
|
||||||
.id()
|
|
||||||
.field("title", .string, .required)
|
|
||||||
.create()
|
|
||||||
}
|
|
||||||
|
|
||||||
func revert(on database: any Database) async throws {
|
|
||||||
try await database.schema("todos").delete()
|
|
||||||
}
|
|
||||||
}
|
|
50
Sources/stella/Models/Account.swift
Normal file
50
Sources/stella/Models/Account.swift
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import Fluent
|
||||||
|
import struct Foundation.UUID
|
||||||
|
|
||||||
|
/// Property wrappers interact poorly with `Sendable` checking, causing a warning for the `@ID` property
|
||||||
|
/// It is recommended you write your model with sendability checking on and then suppress the warning
|
||||||
|
/// afterwards with `@unchecked Sendable`.
|
||||||
|
final class Account: Model, @unchecked Sendable {
|
||||||
|
static let schema = "accounts"
|
||||||
|
|
||||||
|
@ID(custom: "id", generatedBy: .database)
|
||||||
|
var id: Int?
|
||||||
|
|
||||||
|
@Field(key: "app_id")
|
||||||
|
var appId: String
|
||||||
|
|
||||||
|
@Field(key: "first_login_time")
|
||||||
|
var firstLogin: Date
|
||||||
|
|
||||||
|
@Field(key: "reg_time")
|
||||||
|
var regDate: Date
|
||||||
|
|
||||||
|
@Field(key: "last_login_time")
|
||||||
|
var lastLogin: Date
|
||||||
|
|
||||||
|
@Field(key: "idp_alias")
|
||||||
|
var idpAlias: String
|
||||||
|
|
||||||
|
@Field(key: "idp_code")
|
||||||
|
var idpCode: String
|
||||||
|
|
||||||
|
@Field(key: "idp_id")
|
||||||
|
var idpId: String
|
||||||
|
|
||||||
|
@Field(key: "status")
|
||||||
|
var status: String
|
||||||
|
|
||||||
|
init() { }
|
||||||
|
|
||||||
|
init(id: Int? = nil, appId: String, idpAlias: String, idpCode: String, idpId: String, status: String) {
|
||||||
|
self.id = id
|
||||||
|
self.appId = appId
|
||||||
|
self.firstLogin = Date.now
|
||||||
|
self.idpAlias = idpAlias
|
||||||
|
self.idpCode = idpCode
|
||||||
|
self.idpId = idpId
|
||||||
|
self.regDate = Date.now
|
||||||
|
self.lastLogin = Date.now
|
||||||
|
self.status = status
|
||||||
|
}
|
||||||
|
}
|
@@ -1,29 +0,0 @@
|
|||||||
import Fluent
|
|
||||||
import struct Foundation.UUID
|
|
||||||
|
|
||||||
/// Property wrappers interact poorly with `Sendable` checking, causing a warning for the `@ID` property
|
|
||||||
/// It is recommended you write your model with sendability checking on and then suppress the warning
|
|
||||||
/// afterwards with `@unchecked Sendable`.
|
|
||||||
final class Todo: Model, @unchecked Sendable {
|
|
||||||
static let schema = "todos"
|
|
||||||
|
|
||||||
@ID(key: .id)
|
|
||||||
var id: UUID?
|
|
||||||
|
|
||||||
@Field(key: "title")
|
|
||||||
var title: String
|
|
||||||
|
|
||||||
init() { }
|
|
||||||
|
|
||||||
init(id: UUID? = nil, title: String) {
|
|
||||||
self.id = id
|
|
||||||
self.title = title
|
|
||||||
}
|
|
||||||
|
|
||||||
func toDTO() -> TodoDTO {
|
|
||||||
.init(
|
|
||||||
id: self.id,
|
|
||||||
title: self.$title.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -10,7 +10,7 @@ public func configure(_ app: Application) async throws {
|
|||||||
|
|
||||||
app.databases.use(DatabaseConfigurationFactory.sqlite(.file("db.sqlite")), as: .sqlite)
|
app.databases.use(DatabaseConfigurationFactory.sqlite(.file("db.sqlite")), as: .sqlite)
|
||||||
|
|
||||||
app.migrations.add(CreateTodo())
|
app.migrations.add(CreateAccount())
|
||||||
app.http.server.configuration.hostname = "0.0.0.0"
|
app.http.server.configuration.hostname = "0.0.0.0"
|
||||||
app.http.server.configuration.port = 8000
|
app.http.server.configuration.port = 8000
|
||||||
|
|
||||||
|
@@ -8,16 +8,16 @@ enum Entrypoint {
|
|||||||
static func main() async throws {
|
static func main() async throws {
|
||||||
var env = try Environment.detect()
|
var env = try Environment.detect()
|
||||||
try LoggingSystem.bootstrap(from: &env)
|
try LoggingSystem.bootstrap(from: &env)
|
||||||
|
|
||||||
let app = try await Application.make(env)
|
let app = try await Application.make(env)
|
||||||
|
|
||||||
// This attempts to install NIO as the Swift Concurrency global executor.
|
// This attempts to install NIO as the Swift Concurrency global executor.
|
||||||
// You can enable it if you'd like to reduce the amount of context switching between NIO and Swift Concurrency.
|
// You can enable it if you'd like to reduce the amount of context switching between NIO and Swift Concurrency.
|
||||||
// Note: this has caused issues with some libraries that use `.wait()` and cleanly shutting down.
|
// Note: this has caused issues with some libraries that use `.wait()` and cleanly shutting down.
|
||||||
// If enabled, you should be careful about calling async functions before this point as it can cause assertion failures.
|
// If enabled, you should be careful about calling async functions before this point as it can cause assertion failures.
|
||||||
// let executorTakeoverSuccess = NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor()
|
let executorTakeoverSuccess = NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor()
|
||||||
// app.logger.debug("Tried to install SwiftNIO's EventLoopGroup as Swift's global concurrency executor", metadata: ["success": .stringConvertible(executorTakeoverSuccess)])
|
app.logger.debug("Tried to install SwiftNIO's EventLoopGroup as Swift's global concurrency executor", metadata: ["success": .stringConvertible(executorTakeoverSuccess)])
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await configure(app)
|
try await configure(app)
|
||||||
try await app.execute()
|
try await app.execute()
|
||||||
|
@@ -10,10 +10,6 @@ func routes(_ app: Application) throws {
|
|||||||
"Hello, world!"
|
"Hello, world!"
|
||||||
}
|
}
|
||||||
|
|
||||||
let openApi = OpenApi()
|
|
||||||
openApi.registerRoutes(app)
|
|
||||||
|
|
||||||
try app.register(collection: InfodeskController())
|
try app.register(collection: InfodeskController())
|
||||||
|
try app.register(collection: OpenApiController())
|
||||||
print(app.routes.all)
|
|
||||||
}
|
}
|
@@ -1,140 +0,0 @@
|
|||||||
import Vapor
|
|
||||||
|
|
||||||
struct OpenApi {
|
|
||||||
func registerRoutes(_ app: Application) {
|
|
||||||
let group = app.grouped("openapi", "service")
|
|
||||||
|
|
||||||
group.post("v3", "util", "country", "get") { req async -> String in
|
|
||||||
"{\"country\": \"us\"}"
|
|
||||||
}
|
|
||||||
|
|
||||||
group.post("v4", "device", "accessToken", "create") { req async -> AccessTokenResponse in
|
|
||||||
AccessTokenResponse(accessToken: "fwPla7fQ8ty9+DZT/lD//uWZD4uD6C4lD6gGIIZTLKRTQ52/SLCRmk/370jcWGs+e+1iSoZtL7lj8ov9B0/jHmijH4nsHPQT6pchaQM1M9mtwYNQq0BWhVr9hF0jjCK/a5LIVd1kBac/Gemv29WKEDKSrUS9HxxUigoPRwtOy8m+oDj9FmDJZ+rzqWCc0QjES4Ky0fTpXZ7ESoguDzNmRtW3FYr+OFexw8wBPlwiC4w=", expiryTime: Int(Date.init(timeIntervalSinceNow: .init(0)).timeIntervalSince1970))
|
|
||||||
}
|
|
||||||
|
|
||||||
group.post("v3", "agreement", "getForLogin") { req async throws -> String in
|
|
||||||
let body = try req.content.decode(LoginAgreementRequest.self, as: .json)
|
|
||||||
|
|
||||||
return #"""
|
|
||||||
{
|
|
||||||
"adAgreementStatus": "n",
|
|
||||||
"agreement": {
|
|
||||||
"E001": "n",
|
|
||||||
"E002": "n",
|
|
||||||
"E006": "n",
|
|
||||||
"N002": "n",
|
|
||||||
"N003": "n",
|
|
||||||
"timestamp": "\#(Int(Date().timeIntervalSince1970) * 1000)"
|
|
||||||
},
|
|
||||||
"agreementPopup": "n",
|
|
||||||
"appId": "\#(body.appId)",
|
|
||||||
"appName": "World Flipper (NA)",
|
|
||||||
"context": "login",
|
|
||||||
"country": "\#(body.country)",
|
|
||||||
"firstAgreement": "n",
|
|
||||||
"idpCode": "\#(body.idpCode)",
|
|
||||||
"idpId": "6076008646",
|
|
||||||
"informationSecurityCountry": "kr",
|
|
||||||
"kakaoSyncAgreementGetSet": "n",
|
|
||||||
"kakaoSyncStatus": "off",
|
|
||||||
"kakaogameSdkVer": "3.0",
|
|
||||||
"lang": "\#(body.lang)",
|
|
||||||
"partnerId": 825,
|
|
||||||
"partnerName": "주식회사 카카오게임즈",
|
|
||||||
"plusFriendStatusInfo": null,
|
|
||||||
"policyApplyTime": 1630854000000
|
|
||||||
}
|
|
||||||
"""#
|
|
||||||
}
|
|
||||||
|
|
||||||
group.post("v4", "auth", "loginDevice") { req async throws -> Response in
|
|
||||||
let body = try req.content.decode(LoginDeviceRequest.self, as: .json)
|
|
||||||
dump(body)
|
|
||||||
if let rawAccountId = req.headers["playerId"].first {
|
|
||||||
|
|
||||||
}
|
|
||||||
return Response(status: .notImplemented)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AccessTokenResponse: Content {
|
|
||||||
let accessToken: String
|
|
||||||
let expiryTime: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LoginAgreementRequest: Content {
|
|
||||||
let deviceId: String
|
|
||||||
let os: String
|
|
||||||
let country: String
|
|
||||||
let lang: String
|
|
||||||
let appId: String
|
|
||||||
let idpCode: String
|
|
||||||
let serialNo: String
|
|
||||||
let idpId: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LoginDeviceRequest: Content {
|
|
||||||
let lang: String
|
|
||||||
let clientTime: Int
|
|
||||||
let deviceId: String
|
|
||||||
let serialNo: String
|
|
||||||
let country: String
|
|
||||||
let whiteKey: String
|
|
||||||
let market: String
|
|
||||||
let appSecret: String
|
|
||||||
let deviceAppKey: String
|
|
||||||
let sdkVer: String
|
|
||||||
let appVer: String
|
|
||||||
let os: String
|
|
||||||
let loginType: String
|
|
||||||
let accessToken: String
|
|
||||||
let resume: Bool
|
|
||||||
let osVer: String
|
|
||||||
let appId: String
|
|
||||||
let deviceModel: String
|
|
||||||
let network: String
|
|
||||||
let isIosAppOnMac: Bool
|
|
||||||
let adid: String
|
|
||||||
let timezoneOffset: Int
|
|
||||||
let fields: [String]
|
|
||||||
let telecom: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LoginDeviceResponse: Content {
|
|
||||||
let zatExpiryTime: Int
|
|
||||||
let zrtExpiryTime: Int
|
|
||||||
let firstLogin: Bool
|
|
||||||
let externalToken: String
|
|
||||||
let zat: String
|
|
||||||
let zrt: String
|
|
||||||
let player: Player
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Player: Content {
|
|
||||||
let idpId: String
|
|
||||||
let appId: String
|
|
||||||
let lang: String
|
|
||||||
let playerId: String
|
|
||||||
let agreement: AgreementResponse
|
|
||||||
let pushOption: PushOptionResponse
|
|
||||||
let lastLoginTime: Int
|
|
||||||
let regTime: Int
|
|
||||||
let idpAlias: String
|
|
||||||
let firstLoginTime: Int
|
|
||||||
let status: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AgreementResponse: Content {
|
|
||||||
let E001: String
|
|
||||||
let E002: String
|
|
||||||
let E006: String
|
|
||||||
let N002: String
|
|
||||||
let N003: String
|
|
||||||
let timestamp: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PushOptionResponse: Content {
|
|
||||||
let night: String
|
|
||||||
let player: String
|
|
||||||
}
|
|
3
Sources/stella/util.swift
Normal file
3
Sources/stella/util.swift
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
func generateIdpAlias(appId: String, deviceId: String, serialNo: String) -> String {
|
||||||
|
return "\(appId):\(deviceId):\(serialNo)"
|
||||||
|
}
|
Reference in New Issue
Block a user