mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
177 lines
6.2 KiB
Swift
177 lines
6.2 KiB
Swift
import Foundation
|
|
|
|
/// Server-side team with elevated access and server metadata
|
|
public actor ServerTeam {
|
|
private let client: APIClient
|
|
|
|
public nonisolated let id: String
|
|
public private(set) var displayName: String
|
|
public private(set) var profileImageUrl: String?
|
|
public private(set) var clientMetadata: [String: Any]
|
|
public private(set) var clientReadOnlyMetadata: [String: Any]
|
|
public private(set) var serverMetadata: [String: Any]
|
|
public let createdAt: Date
|
|
|
|
init(client: APIClient, json: [String: Any]) {
|
|
self.client = client
|
|
self.id = json["id"] as? String ?? ""
|
|
self.displayName = json["display_name"] as? String ?? ""
|
|
self.profileImageUrl = json["profile_image_url"] as? String
|
|
self.clientMetadata = json["client_metadata"] as? [String: Any] ?? [:]
|
|
self.clientReadOnlyMetadata = json["client_read_only_metadata"] as? [String: Any] ?? [:]
|
|
self.serverMetadata = json["server_metadata"] as? [String: Any] ?? [:]
|
|
|
|
let createdMillis = json["created_at_millis"] as? Int64 ?? 0
|
|
self.createdAt = Date(timeIntervalSince1970: Double(createdMillis) / 1000.0)
|
|
}
|
|
|
|
// MARK: - Update
|
|
|
|
public func update(
|
|
displayName: String? = nil,
|
|
profileImageUrl: String? = nil,
|
|
clientMetadata: [String: Any]? = nil,
|
|
clientReadOnlyMetadata: [String: Any]? = nil,
|
|
serverMetadata: [String: Any]? = nil
|
|
) async throws {
|
|
var body: [String: Any] = [:]
|
|
if let displayName = displayName { body["display_name"] = displayName }
|
|
if let url = profileImageUrl { body["profile_image_url"] = url }
|
|
if let clientMeta = clientMetadata { body["client_metadata"] = clientMeta }
|
|
if let clientReadOnly = clientReadOnlyMetadata { body["client_read_only_metadata"] = clientReadOnly }
|
|
if let serverMeta = serverMetadata { body["server_metadata"] = serverMeta }
|
|
|
|
let (data, _) = try await client.sendRequest(
|
|
path: "/teams/\(id)",
|
|
method: "PATCH",
|
|
body: body,
|
|
serverOnly: true
|
|
)
|
|
|
|
if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
self.displayName = json["display_name"] as? String ?? self.displayName
|
|
self.profileImageUrl = json["profile_image_url"] as? String
|
|
self.clientMetadata = json["client_metadata"] as? [String: Any] ?? self.clientMetadata
|
|
self.clientReadOnlyMetadata = json["client_read_only_metadata"] as? [String: Any] ?? self.clientReadOnlyMetadata
|
|
self.serverMetadata = json["server_metadata"] as? [String: Any] ?? self.serverMetadata
|
|
}
|
|
}
|
|
|
|
// MARK: - Delete
|
|
|
|
public func delete() async throws {
|
|
_ = try await client.sendRequest(
|
|
path: "/teams/\(id)",
|
|
method: "DELETE",
|
|
serverOnly: true
|
|
)
|
|
}
|
|
|
|
// MARK: - Users
|
|
|
|
public func listUsers() async throws -> [TeamUser] {
|
|
let (data, _) = try await client.sendRequest(
|
|
path: "/users?team_id=\(id)",
|
|
method: "GET",
|
|
serverOnly: true
|
|
)
|
|
|
|
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let items = json["items"] as? [[String: Any]] else {
|
|
return []
|
|
}
|
|
|
|
return items.map { TeamUser(from: $0) }
|
|
}
|
|
|
|
public func addUser(id userId: String) async throws {
|
|
_ = try await client.sendRequest(
|
|
path: "/team-memberships/\(id)/\(userId)",
|
|
method: "POST",
|
|
serverOnly: true
|
|
)
|
|
}
|
|
|
|
public func removeUser(id userId: String) async throws {
|
|
_ = try await client.sendRequest(
|
|
path: "/team-memberships/\(id)/\(userId)",
|
|
method: "DELETE",
|
|
serverOnly: true
|
|
)
|
|
}
|
|
|
|
// MARK: - Invitations
|
|
|
|
public func inviteUser(email: String, callbackUrl: String? = nil) async throws {
|
|
var body: [String: Any] = [
|
|
"email": email,
|
|
"team_id": id
|
|
]
|
|
if let url = callbackUrl { body["callback_url"] = url }
|
|
|
|
_ = try await client.sendRequest(
|
|
path: "/team-invitations/send-code",
|
|
method: "POST",
|
|
body: body,
|
|
serverOnly: true
|
|
)
|
|
}
|
|
|
|
public func listInvitations() async throws -> [TeamInvitation] {
|
|
let (data, _) = try await client.sendRequest(
|
|
path: "/teams/\(id)/invitations",
|
|
method: "GET",
|
|
serverOnly: true
|
|
)
|
|
|
|
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let items = json["items"] as? [[String: Any]] else {
|
|
return []
|
|
}
|
|
|
|
return items.map { TeamInvitation(client: client, teamId: id, json: $0) }
|
|
}
|
|
|
|
// MARK: - API Keys
|
|
|
|
public func listApiKeys() async throws -> [TeamApiKey] {
|
|
let (data, _) = try await client.sendRequest(
|
|
path: "/teams/\(id)/api-keys",
|
|
method: "GET",
|
|
serverOnly: true
|
|
)
|
|
|
|
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let items = json["items"] as? [[String: Any]] else {
|
|
return []
|
|
}
|
|
|
|
return items.map { TeamApiKey(from: $0) }
|
|
}
|
|
|
|
public func createApiKey(
|
|
description: String,
|
|
expiresAt: Date? = nil,
|
|
scope: String? = nil
|
|
) async throws -> TeamApiKeyFirstView {
|
|
var body: [String: Any] = ["description": description]
|
|
if let expiresAt = expiresAt {
|
|
body["expires_at_millis"] = Int64(expiresAt.timeIntervalSince1970 * 1000)
|
|
}
|
|
if let scope = scope { body["scope"] = scope }
|
|
|
|
let (data, _) = try await client.sendRequest(
|
|
path: "/teams/\(id)/api-keys",
|
|
method: "POST",
|
|
body: body,
|
|
serverOnly: true
|
|
)
|
|
|
|
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
throw StackAuthError(code: "parse_error", message: "Failed to parse API key response")
|
|
}
|
|
|
|
return TeamApiKeyFirstView(from: json)
|
|
}
|
|
}
|