stack/sdks/implementations/swift/Sources/StackAuth/Models/ServerTeam.swift
Konstantin Wohlwend 66b066db6e Swift SDK
2026-01-19 13:14:13 -08:00

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)
}
}