atproto pds in zig pds.zat.dev
pds atproto
Something went wrong. Try again.
Zig
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108const std = @import("std");const zds = @import("zds");
const Io = std.Io;
var app_threaded_io: Io.Threaded = undefined;pub const std_options_debug_threaded_io: ?*Io.Threaded = &app_threaded_io;
pub fn main(init: std.process.Init) !void { const allocator = std.heap.smp_allocator; app_threaded_io = Io.Threaded.init(allocator, .{}); const io = app_threaded_io.io();
const did = parseDid(init) orelse { std.debug.print("usage: zds-plc-repair DID\n", .{}); return error.MissingDid; };
if (env("ZDS_PUBLIC_URL")) |value| zds.core.config.setPublicUrl(value); if (env("ZDS_PLC_DIRECTORY")) |value| zds.core.config.setPlcDirectory(value); zds.core.config.setPlcRotationKey(env("ZDS_PLC_ROTATION_KEY")); zds.core.config.setRecoveryDidKey(env("ZDS_RECOVERY_DID_KEY"));
const db_path = env("ZDS_DB_PATH") orelse env("ZDS_DB") orelse "dev/zds.sqlite3"; try zds.storage.store.init(io, db_path);
const account = (try zds.storage.store.findAccount(allocator, did)) orelse return error.AccountNotFound; var account_keypair = try zds.storage.store.signingKeypair(account.did); const account_did_key = try account_keypair.did(allocator); var rotation_keypair = try zds.atproto.plc.configuredRotationKeypair(); const rotation_did_key = try rotation_keypair.did(allocator);
const last_op = try zds.atproto.plc.fetchLastOperation(allocator, account.did); const current_rotation_keys = zds.zat.json.getPath(last_op, "rotationKeys"); const signer = if (jsonArrayContainsString(current_rotation_keys, rotation_did_key)) &rotation_keypair else if (jsonArrayContainsString(current_rotation_keys, account_did_key)) &account_keypair else return error.NoControlledCurrentRotationKey;
const target_rotation_keys = try targetRotationKeys(allocator, rotation_did_key); if (stringListContains(target_rotation_keys, account_did_key)) { return error.AccountSigningKeyWouldRemainRotationKey; }
const prev = try zds.atproto.plc.cidForJsonValue(allocator, last_op); const unsigned = try zds.atproto.plc.updateOperationJson(allocator, account.handle, account_did_key, target_rotation_keys, prev); const signed = try zds.atproto.plc.signOperationJson(allocator, unsigned, signer); try zds.atproto.plc.submitOperation(allocator, account.did, signed);
std.debug.print("repaired PLC rotation keys for {s}\n", .{account.did});}
fn parseDid(init: std.process.Init) ?[]const u8 { var args = std.process.Args.Iterator.init(init.minimal.args); _ = args.next(); return args.next();}
fn env(name: [:0]const u8) ?[]const u8 { const value = std.c.getenv(name) orelse return null; return std.mem.span(value);}
fn targetRotationKeys(allocator: std.mem.Allocator, rotation_did_key: []const u8) ![]const []const u8 { const repair_recovery = try repairRecoveryDidKey(allocator); const recovery = repair_recovery orelse zds.core.config.recoveryDidKey(); const count: usize = if (recovery == null) 1 else 2; const keys = try allocator.alloc([]const u8, count); var idx: usize = 0; if (recovery) |value| { keys[idx] = value; idx += 1; } keys[idx] = rotation_did_key; return keys;}
fn repairRecoveryDidKey(allocator: std.mem.Allocator) !?[]const u8 { if (env("ZDS_REPAIR_RECOVERY_DID_KEY")) |did_key| return did_key; if (env("ZDS_REPAIR_RECOVERY_KEY")) |private_key| { var keypair = try zds.atproto.plc.parsePrivateKey(allocator, private_key); const did_key = try keypair.did(allocator); return did_key; } return null;}
fn jsonArrayContainsString(value: ?std.json.Value, expected: []const u8) bool { const items = switch (value orelse return false) { .array => |array| array.items, else => return false, }; for (items) |item| switch (item) { .string => |string| if (std.mem.eql(u8, string, expected)) return true, else => {}, }; return false;}
fn stringListContains(items: []const []const u8, expected: []const u8) bool { for (items) |item| { if (std.mem.eql(u8, item, expected)) return true; } return false;}