wao 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,858 +0,0 @@
1
- local json = require('json')
2
- local sqlite3 = require('lsqlite3')
3
-
4
- Db = Db or sqlite3.open_memory()
5
- ao.addAssignable("AssignableRule", { Action = '_' })
6
- local HandlerRoles = {
7
- ['Update-Profile'] = {'Owner', 'Admin'},
8
- ['Add-Uploaded-Asset'] = {'Owner', 'Admin', 'Contributor'},
9
- ['Add-Collection'] = {'Owner', 'Admin', 'Contributor'},
10
- ['Update-Collection-Sort'] = {'Owner', 'Admin'},
11
- ['Transfer'] = {'Owner', 'Admin'},
12
- ['Debit-Notice'] = {'Owner', 'Admin'},
13
- ['Credit-Notice'] = {'Owner', 'Admin'},
14
- ['Action-Response'] = {'Owner', 'Admin'},
15
- ['Run-Action'] = {'Owner', 'Admin'},
16
- ['Proxy-Action'] = {'Owner', 'Admin'},
17
- ['Update-Role'] = {'Owner', 'Admin'}
18
- }
19
-
20
- local function decode_message_data(data)
21
- local status, decoded_data = pcall(json.decode, data)
22
- if not status or type(decoded_data) ~= 'table' then
23
- return false, nil
24
- end
25
- return true, decoded_data
26
- end
27
-
28
- local function is_authorized(profile_id, user_id, roles)
29
- if not profile_id then
30
- return false
31
- end
32
- local query = [[
33
- SELECT role
34
- FROM ao_profile_authorization
35
- WHERE profile_id = ? AND delegate_address = ?
36
- LIMIT 1
37
- ]]
38
- local stmt = Db:prepare(query)
39
- stmt:bind_values(profile_id, user_id)
40
- local authorized = false
41
- for row in stmt:nrows() do
42
- for _, role in ipairs(roles) do
43
- if row.role == role then
44
- authorized = true
45
- break
46
- end
47
- end
48
- end
49
- stmt:finalize()
50
- return authorized
51
- end
52
-
53
- local function process_profile_action(msg)
54
-
55
- local reply_to = msg.From
56
- local decode_check, data = decode_message_data(msg.Data)
57
- if not decode_check then
58
- ao.send({
59
- Target = reply_to,
60
- Action = 'ERROR',
61
- Tags = {
62
- Status = 'DECODE_FAILED',
63
- Message = "Failed to decode data"
64
- },
65
- Data = { Code = "DECODE_FAILED" }
66
- })
67
- return
68
- end
69
- local tags = msg.Tags or {}
70
- -- see if new version of update
71
- -- handle legacy authorized_address tag
72
- local legacy_authorized_address = tags.AuthorizedAddress or decode_check and data.AuthorizedAddress or nil
73
- -- new api: profile_id is msg id on spawn or msg.Target in update
74
- local target = msg.Target and msg.Target ~= "" and msg.Target or nil
75
- local profile_id = legacy_authorized_address and msg.From or target or msg.Id -- create = msg.Id spawn
76
- local user_id = legacy_authorized_address or msg.From -- (assigned) -- AuthorizedAddress
77
-
78
- -- new api: after spawn, updates assigned will need to include ProfileProcess tag or data
79
-
80
- -- update and new api if msg.Tags.Type == "Message" and msg.Target ~= ao.id (Self)
81
-
82
- local is_update = msg.Tags.Type == "Message" and msg.Target ~= ao.id or false -- and action == "Create-Profile" or action == "Update-Profile"
83
- -- handle legacy "every update is create action" bug by checking roles first
84
- if not is_update then
85
- local check = Db:prepare('SELECT 1 FROM ao_profile_authorization WHERE delegate_address = ? AND profile_id = ? LIMIT 1')
86
- check:bind_values(user_id, profile_id)
87
- if check:step() ~= sqlite3.ROW then
88
- is_update = false
89
- local insert_auth = Db:prepare(
90
- 'INSERT INTO ao_profile_authorization (profile_id, delegate_address, role) VALUES (?, ?, ?)')
91
- insert_auth:bind_values(profile_id, user_id, 'Owner')
92
- insert_auth:step()
93
- insert_auth:finalize()
94
- else
95
- is_update = true
96
- end
97
- end
98
-
99
- if is_update and not is_authorized(profile_id, user_id, HandlerRoles['Update-Profile']) then
100
- ao.send({
101
- Target = reply_to,
102
- Action = 'Authorization-Error',
103
- Tags = {
104
- Status = 'Error',
105
- Message = 'Unauthorized to access this handler'
106
- }
107
- })
108
- return
109
- end
110
-
111
- local columns = {}
112
- local placeholders = {}
113
- local params = {}
114
- local metadataValues = {
115
- id = profile_id,
116
- username = msg.Tags.UserName or decode_check and data.UserName or nil,
117
- profile_image = msg.Tags.ProfileImage or decode_check and data.ProfileImage or nil,
118
- cover_image = msg.Tags.CoverImage or decode_check and data.CoverImage or nil,
119
- description = msg.Tags.Description or decode_check and data.Description or nil,
120
- display_name = msg.Tags.DisplayName or decode_check and data.DisplayName or nil,
121
- date_updated = msg.Timestamp,
122
- date_created = not is_update and msg.Timestamp or nil
123
- }
124
- local function generateInsertQuery()
125
- for key, val in pairs(metadataValues) do
126
- if val ~= nil then
127
- -- Include the field if provided
128
- table.insert(columns, key)
129
- if val == "" then
130
- -- If the field is an empty string, insert NULL
131
- table.insert(placeholders, "NULL")
132
- else
133
- -- Otherwise, prepare to bind the actual value
134
- table.insert(placeholders, "?")
135
- table.insert(params, val)
136
- end
137
- else
138
- -- If field is nil and not mandatory, insert NULL
139
- if key ~= "id" then
140
- table.insert(columns, key)
141
- table.insert(placeholders, "NULL")
142
- end
143
- end
144
- end
145
-
146
- local sql = "INSERT INTO ao_profile_metadata (" .. table.concat(columns, ", ") .. ")"
147
- sql = sql .. " VALUES (" .. table.concat(placeholders, ", ") .. ")"
148
-
149
- return sql
150
- end
151
-
152
- local function generateUpdateQuery()
153
- -- first create setclauses for everything but id
154
- for key, val in pairs(metadataValues) do
155
- if val ~= nil and val ~= 'id' then
156
- -- Include the field if provided
157
- table.insert(columns, key)
158
- if val == "" then
159
- -- If the field is an empty string, insert NULL
160
- table.insert(placeholders, "NULL")
161
- else
162
- -- Otherwise, prepare to bind the actual value
163
- table.insert(placeholders, "?")
164
- table.insert(params, val)
165
- end
166
- end
167
- end
168
- -- now build querystring
169
- local sql = "UPDATE ao_profile_metadata SET "
170
- for i, _ in ipairs(columns) do
171
- sql = sql .. columns[i] .. " = " .. placeholders[i]
172
- if i ~= #columns then
173
- sql = sql .. ","
174
- end
175
- end
176
- sql = sql .. " WHERE id = ?"
177
- return sql
178
- end
179
- -- A spawn create will have data including UserName
180
- -- A legacy create will only
181
- -- new api: profile assigns the spawn tx to the registry, which contains the data
182
- -- legacy api: profile send()s new message to registry with the data and authorized_address (user_id) of admin
183
- if is_update or (not is_update and (msg.Tags.UserName or decode_check and data.UserName)) then
184
- local sql = not is_update and generateInsertQuery() or generateUpdateQuery()
185
- local stmt = Db:prepare(sql)
186
-
187
- if not stmt then
188
- ao.send({
189
- Target = reply_to,
190
- Action = 'DB_CODE',
191
- Tags = {
192
- Status = 'DB_PREPARE_FAILED',
193
- Message = "DB PREPARED QUERY FAILED"
194
- },
195
- Data = { Code = "Failed to prepare insert statement",
196
- SQL = sql,
197
- ERROR = Db:errmsg()
198
- }
199
- })
200
- print("Failed to prepare insert statement")
201
- return json.encode({ Code = 'DB_PREPARE_FAILED' })
202
- end
203
-
204
- if not is_update then
205
- -- bind values for INSERT statement
206
- stmt:bind_values(table.unpack(params))
207
- else
208
- -- bind values for UPDATE statement (id is last)
209
- table.insert(params, profile_id)
210
- stmt:bind_values(table.unpack(params))
211
- end
212
-
213
- local step_status = stmt:step()
214
- if step_status ~= sqlite3.OK and step_status ~= sqlite3.DONE and step_status ~= sqlite3.ROW then
215
- stmt:finalize()
216
- print("Error: " .. Db:errmsg())
217
- print("SQL" .. sql)
218
- ao.send({
219
- Target = reply_to,
220
- Action = 'DB_STEP_CODE',
221
- Tags = {
222
- Status = 'ERROR',
223
- Message = 'sqlite step error'
224
- },
225
- Data = { DB_STEP_MSG = step_status, IS_UPDATE = tostring(is_update) }
226
- })
227
- return json.encode({ Code = step_status })
228
- end
229
- end
230
-
231
- ao.send({
232
- Target = reply_to,
233
- Action = 'Success',
234
- Tags = {
235
- Status = 'Success',
236
- Message = is_update and 'Record Updated' or 'Record Inserted'
237
- },
238
- Data = json.encode(metadataValues)
239
- })
240
-
241
-
242
- end
243
-
244
- -- Handlers.add('migrate-database', ... , Db:exec [[ ALTER TABLE _ ADD new_field type ]]
245
-
246
- Handlers.add('Prepare-Database', Handlers.utils.hasMatchingTag('Action', 'Prepare-Database'),
247
- function(msg)
248
- if msg.From ~= Owner and msg.From ~= ao.id then
249
- ao.send({
250
- Target = msg.From,
251
- Action = 'Authorization-Error',
252
- Tags = {
253
- Status = 'Error',
254
- Message = 'Unauthorized to access this handler'
255
- }
256
- })
257
- return
258
- end
259
-
260
- --todo create tables for: languages, following, followed, topic-tags, locations, external_links, external_wallets
261
-
262
- Db:exec [[
263
- CREATE TABLE IF NOT EXISTS ao_profile_metadata (
264
- id TEXT PRIMARY KEY NOT NULL,
265
- username TEXT,
266
- display_name TEXT,
267
- description TEXT,
268
- profile_image TEXT,
269
- cover_image TEXT,
270
- date_created INTEGER NOT NULL,
271
- date_updated INTEGER NOT NULL
272
- );
273
- ]]
274
-
275
- Db:exec [[
276
- CREATE TABLE IF NOT EXISTS ao_profile_authorization (
277
- profile_id TEXT NOT NULL,
278
- delegate_address TEXT NOT NULL,
279
- role TEXT NOT NULL,
280
- PRIMARY KEY (profile_id, delegate_address),
281
- FOREIGN KEY (profile_id) REFERENCES ao_profile_metadata (id) ON DELETE CASCADE
282
- );
283
- ]]
284
-
285
- ao.send({
286
- Target = Owner,
287
- Action = 'DB-Init-Success',
288
- Tags = {
289
- Status = 'Success',
290
- Message = 'Created DB'
291
- }
292
- })
293
- end)
294
-
295
- -- Data - { ProfileIds [] }
296
- Handlers.add('Get-Metadata-By-ProfileIds', Handlers.utils.hasMatchingTag('Action', 'Get-Metadata-By-ProfileIds'),
297
- function(msg)
298
-
299
- local decode_check, data = decode_message_data(msg.Data)
300
-
301
- if decode_check and data then
302
- if not data.ProfileIds then
303
- ao.send({
304
- Target = msg.From,
305
- Action = 'Input-Error',
306
- Tags = {
307
- Status = 'Error',
308
- Message = 'Invalid arguments, required { ProfileIds }'
309
- },
310
- Data = msg.Data
311
- })
312
- return
313
- end
314
-
315
- local metadata = {}
316
- if #data.ProfileIds > 0 then
317
- local placeholders = {}
318
-
319
- for _, _ in ipairs(data.ProfileIds) do
320
- table.insert(placeholders, "?")
321
- end
322
-
323
- if #placeholders > 0 then
324
- local stmt = Db:prepare([[
325
- SELECT *
326
- FROM ao_profile_metadata
327
- WHERE id IN (]] .. table.concat(placeholders, ',') .. [[)
328
- ]])
329
-
330
- if not stmt then
331
- ao.send({
332
- Target = msg.From,
333
- Action = 'DB_CODE',
334
- Tags = {
335
- Status = 'DB_PREPARE_FAILED',
336
- Message = "DB PREPARED QUERY FAILED"
337
- },
338
- Data = { Code = "Failed to prepare insert statement" }
339
- })
340
- print("Failed to prepare insert statement")
341
- return json.encode({ Code = 'DB_PREPARE_FAILED' })
342
- end
343
-
344
- stmt:bind_values(table.unpack(data.ProfileIds))
345
-
346
- local foundRows = false
347
- for row in stmt:nrows() do
348
- foundRows = true
349
- table.insert(metadata, { ProfileId = row.id,
350
- Username = row.username,
351
- ProfileImage = row.profile_image,
352
- CoverImage = row.cover_image,
353
- Description = row.description,
354
- DisplayName = row.display_name
355
- })
356
- end
357
-
358
- if not foundRows then
359
- print('No rows found matching the criteria.')
360
- end
361
-
362
- ao.send({
363
- Target = msg.From,
364
- Action = 'Get-Metadata-Success',
365
- Tags = {
366
- Status = 'Success',
367
- Message = 'Metadata retrieved',
368
- },
369
- Data = json.encode(metadata)
370
- })
371
- else
372
- print('Profile ID list is empty after validation.')
373
- end
374
- else
375
- ao.send({
376
- Target = msg.From,
377
- Action = 'Input-Error',
378
- Tags = {
379
- Status = 'Error',
380
- Message = 'No ProfileIds provided or the list is empty.'
381
- }
382
- })
383
- print('No ProfileIds provided or the list is empty.')
384
- return
385
-
386
- end
387
- else
388
- ao.send({
389
- Target = msg.From,
390
- Action = 'Input-Error',
391
- Tags = {
392
- Status = 'Error',
393
- Message = string.format(
394
- 'Failed to parse data, received: %s. %s.', msg.Data,
395
- 'Data must be an object - { ProfileIds }')
396
- }
397
- })
398
- end
399
- end)
400
-
401
- -- Data - { Address }
402
- Handlers.add('Get-Profiles-By-Delegate', Handlers.utils.hasMatchingTag('Action', 'Get-Profiles-By-Delegate'),
403
- function(msg)
404
- local decode_check, data = decode_message_data(msg.Data)
405
-
406
- if decode_check and data then
407
- if not data.Address then
408
- ao.send({
409
- Target = msg.From,
410
- Action = 'Input-Error',
411
- Tags = {
412
- Status = 'Error',
413
- Message = 'Invalid arguments, required { Address }'
414
- }
415
- })
416
- return
417
- end
418
-
419
- local associated_profiles = {}
420
-
421
- local authorization_lookup = Db:prepare([[
422
- SELECT profile_id, delegate_address, role
423
- FROM ao_profile_authorization
424
- WHERE delegate_address = ?
425
- ]])
426
-
427
- authorization_lookup:bind_values(data.Address)
428
-
429
- for row in authorization_lookup:nrows() do
430
- table.insert(associated_profiles, {
431
- ProfileId = row.profile_id,
432
- CallerAddress = row.delegate_address,
433
- Role = row.role
434
- })
435
- end
436
-
437
- authorization_lookup:finalize()
438
-
439
- if #associated_profiles > 0 then
440
- ao.send({
441
- Target = msg.From,
442
- Action = 'Profile-Success',
443
- Tags = {
444
- Status = 'Success',
445
- Message = 'Associated profiles fetched'
446
- },
447
- Data = json.encode(associated_profiles)
448
- })
449
- else
450
- ao.send({
451
- Target = msg.From,
452
- Action = 'Profile-Error',
453
- Tags = {
454
- Status = 'Error',
455
- Message = 'This wallet address is not associated with a profile'
456
- }
457
- })
458
- end
459
- else
460
- ao.send({
461
- Target = msg.From,
462
- Action = 'Input-Error',
463
- Tags = {
464
- Status = 'Error',
465
- Message = string.format(
466
- 'Failed to parse data, received: %s. %s.', msg.Data,
467
- 'Data must be an object - { Address }')
468
- }
469
- })
470
- end
471
- end)
472
-
473
- -- Data - { Addresses }
474
- Handlers.add('Read-Profiles', Handlers.utils.hasMatchingTag('Action', 'Read-Profiles'),
475
- function(msg)
476
- local json = require 'json'
477
-
478
- local function decode_message_data(data)
479
- local status, decoded_data = pcall(json.decode, data)
480
- if not status or type(decoded_data) ~= 'table' then
481
- return false, nil
482
- end
483
- return true, decoded_data
484
- end
485
-
486
- local decode_check, data = decode_message_data(msg.Data)
487
-
488
- if decode_check and data then
489
- if not data.Addresses or type(data.Addresses) ~= 'table' then
490
- ao.send({
491
- Target = msg.From,
492
- Action = 'Input-Error',
493
- Tags = {
494
- Status = 'Error',
495
- Message = 'Invalid arguments, required { Addresses }'
496
- }
497
- })
498
- return
499
- end
500
-
501
- local associated_profiles = {}
502
-
503
- -- Create placeholders
504
- local placeholders = {}
505
- for i = 1, #data.Addresses do
506
- table.insert(placeholders, '?')
507
- end
508
- local placeholders_str = table.concat(placeholders, ', ')
509
-
510
- -- Prepare the SQL query
511
- local sql_query = [[
512
- SELECT profile_id, delegate_address
513
- FROM ao_profile_authorization
514
- WHERE delegate_address IN (]] .. placeholders_str .. [[)
515
- ]]
516
-
517
- local authorization_lookup = Db:prepare(sql_query)
518
-
519
- -- Bind values
520
- for i, address in ipairs(data.Addresses) do
521
- authorization_lookup:bind(i, address)
522
- end
523
-
524
- -- Execute query and gather results
525
- for row in authorization_lookup:nrows() do
526
- table.insert(associated_profiles, {
527
- ProfileId = row.profile_id,
528
- CallerAddress = row.delegate_address
529
- })
530
- end
531
-
532
- authorization_lookup:finalize()
533
-
534
- if #associated_profiles > 0 then
535
- ao.send({
536
- Target = msg.From,
537
- Action = 'Profile-Success',
538
- Tags = {
539
- Status = 'Success',
540
- Message = 'Associated profiles fetched'
541
- },
542
- Data = json.encode(associated_profiles)
543
- })
544
- else
545
- ao.send({
546
- Target = msg.From,
547
- Action = 'Profile-Error',
548
- Tags = {
549
- Status = 'Error',
550
- Message = 'No profiles associated with the provided addresses'
551
- }
552
- })
553
- end
554
- else
555
- ao.send({
556
- Target = msg.From,
557
- Action = 'Input-Error',
558
- Tags = {
559
- Status = 'Error',
560
- Message = string.format(
561
- 'Failed to parse data, received: %s. %s.', msg.Data,
562
- 'Data must be an object - { Addresses }')
563
- }
564
- })
565
- end
566
- end)
567
-
568
- -- Create-Profile Handler (Original spawned profile message)
569
- Handlers.add('Create-Profile', Handlers.utils.hasMatchingTag('Action', 'Create-Profile'),
570
- process_profile_action)
571
-
572
- -- Update-Profile Handler
573
- Handlers.add('Update-Profile', Handlers.utils.hasMatchingTag('Action', 'Update-Profile'),
574
- process_profile_action)
575
-
576
- -- Data - { Id, Op, Role? }
577
- Handlers.add('Update-Role', Handlers.utils.hasMatchingTag('Action', 'Update-Role'),
578
- function(msg)
579
- local decode_check, data = decode_message_data(msg.Data)
580
- local profile_id = msg.Target
581
- local user_id = msg.From
582
- if decode_check and data then
583
- if not data.Id or not data.Op then
584
- ao.send({
585
- Target = profile_id,
586
- Action = 'Input-Error',
587
- Tags = {
588
- Status = 'Error',
589
- Message = 'Invalid arguments, required { Id, Op, Role }'
590
- }
591
- })
592
- return
593
- end
594
- end
595
-
596
- if not is_authorized(profile_id, user_id, HandlerRoles['Update-Role']) then
597
- ao.send({
598
- Target = profile_id,
599
- Action = 'Authorization-Error',
600
- Tags = {
601
- Status = 'Error',
602
- Message = 'Unauthorized to access this handler'
603
- }
604
- })
605
- return
606
- end
607
-
608
-
609
-
610
- local Id = data.Id or msg.Tags.Id
611
- local Role = data.Role or msg.Tags.Role
612
- local Op = data.Op or msg.Tags.Op
613
-
614
- if not Id or not Op then
615
- ao.send({
616
- Target = profile_id,
617
- Action = 'Input-Error',
618
- Tags = {
619
- Status = 'Error',
620
- Message =
621
- 'Invalid arguments, required { Id, Op } in data or tags'
622
- }
623
- })
624
- return
625
- end
626
- -- handle add, update, or remove Ops
627
- local stmt
628
- if data.Op == 'Add' then
629
- stmt = Db:prepare(
630
- 'INSERT INTO ao_profile_authorization (profile_id, delegate_address, role) VALUES (?, ?, ?)')
631
- stmt:bind_values(profile_id, Id, Role)
632
-
633
- elseif data.Op == 'Update' then
634
- stmt = Db:prepare(
635
- 'UPDATE ao_profile_authorization SET role = ? WHERE profile_id = ? AND delegate_address = ?')
636
- stmt:bind_values(Role, profile_id, Id)
637
-
638
- elseif data.Op == 'Delete' then
639
- stmt = Db:prepare(
640
- 'DELETE FROM ao_profile_authorization WHERE profile_id = ? AND delegate_address = ?')
641
- stmt:bind_values(profile_id, Id)
642
- end
643
-
644
- local step_status = stmt:step()
645
- stmt:finalize()
646
- if step_status ~= sqlite3.OK and step_status ~= sqlite3.DONE and step_status ~= sqlite3.ROW then
647
- print("Error: " .. Db:errmsg())
648
- ao.send({
649
- Target = profile_id,
650
- Action = 'DB_STEP_CODE',
651
- Tags = {
652
- Status = 'ERROR',
653
- Message = 'sqlite step error'
654
- },
655
- Data = { DB_STEP_MSG = step_status }
656
- })
657
- return json.encode({ Code = step_status })
658
- end
659
-
660
- ao.send({
661
- Target = profile_id,
662
- Action = 'Success',
663
- Tags = {
664
- Status = 'Success',
665
- Message = 'Auth Record Success'
666
- },
667
- Data = json.encode({ ProfileId = profile_id, DelegateAddress = Id, Role = Role })
668
- })
669
- end
670
- )
671
-
672
- Handlers.add('Count-Profiles', Handlers.utils.hasMatchingTag('Action', 'Count-Profiles'),
673
- function(msg)
674
- local count_sql = [[
675
- SELECT COUNT(*)
676
- FROM ao_profile_metadata
677
- ]]
678
- local stmt = Db:prepare(count_sql)
679
- local result = stmt:step()
680
- local count = 0
681
-
682
- if result == sqlite3.ROW then
683
- count = stmt:get_value(0)
684
- else
685
- count = -1
686
- end
687
-
688
- ao.send({
689
- Target = msg.From,
690
- Action = 'Count-Profiles-Success',
691
- Tags = {
692
- Status = 'Success',
693
- Message = 'Profiles Counted',
694
- },
695
- Data = json.encode({ Count = count })
696
- })
697
- return json.encode({ Count = count })
698
- end)
699
-
700
- Handlers.add('Read-Metadata', Handlers.utils.hasMatchingTag('Action', 'Read-Metadata'),
701
- function(msg)
702
- local metadata = {}
703
- local status, err = pcall(function()
704
- for row in Db:nrows('SELECT id, username, profile_image, cover_image, description, display_name, date_updated, date_created FROM ao_profile_metadata') do
705
- table.insert(metadata, {
706
- id = row.id,
707
- Username = row.username,
708
- ProfileImage = row.profile_image,
709
- CoverImage = row.cover_image,
710
- Description = row.description,
711
- DisplayName = row.display_name,
712
- DateCreated = row.date_created,
713
- DateUpdated = row.date_updated
714
- })
715
- end
716
- end)
717
- if err or not status then
718
- print("Error: ", err)
719
- return
720
- end
721
-
722
- if foundRows == false then
723
- print('No rows found matching the criteria.')
724
- end
725
- ao.send({
726
- Target = msg.From,
727
- Action = 'Read-Metadata-Success',
728
- Tags = {
729
- Status = 'Success',
730
- Message = 'Metadata retrieved',
731
- },
732
- Data = json.encode(metadata)
733
- })
734
-
735
- return json.encode(metadata)
736
- end)
737
-
738
- Handlers.add('Read-Auth', Handlers.utils.hasMatchingTag('Action', 'Read-Auth'),
739
- function(msg)
740
- local metadata = {}
741
- local string = ''
742
- local foundRows = false
743
- local status, err = pcall(function()
744
- for row in Db:nrows('SELECT profile_id, delegate_address, role FROM ao_profile_authorization') do
745
- foundRows = true
746
- table.insert(metadata, {
747
- ProfileId = row.profile_id,
748
- CallerAddress = row.delegate_address,
749
- Role = row.role,
750
- })
751
- string = string .. "ProfileId: " .. row.profile_id .. " CallerAddress: " .. row.delegate_address .. " Role: " .. row.role .. "\n"
752
- end
753
- end)
754
- if not status then
755
- print("Error: ", err)
756
- return
757
- end
758
- ao.send({
759
- Target = msg.From,
760
- Action = 'Read-Metadata-Success',
761
- Tags = {
762
- Status = 'Success',
763
- Message = 'Auth Data retrieved',
764
- },
765
- Data = json.encode(metadata)
766
- })
767
- return json.encode(metadata)
768
- end)
769
-
770
- Handlers.add('Read-Profile', Handlers.utils.hasMatchingTag('Action', 'Read-Profile'),
771
- function(msg)
772
- local decode_check, data = decode_message_data(msg.Data)
773
-
774
- if decode_check ~= true then
775
- ao.send({
776
- Target = msg.From,
777
- Action = 'DB_CODE',
778
- Tags = {
779
- Status = 'DECODE_FAILED',
780
- Message = "Failed to decode data"
781
- },
782
- Data = { Code = "DECODE_FAILED" }
783
- })
784
- return
785
- end
786
-
787
- local selectsql = [[
788
- SELECT *
789
- FROM ao_profile_metadata
790
- WHERE id = ?
791
- ]]
792
-
793
- local row
794
- local select_stmt = Db:prepare(selectsql)
795
- local bind = -1
796
- if select_stmt then
797
- bind = select_stmt:bind_values(data.ProfileId)
798
- else
799
- ao.send({
800
- Target = msg.From,
801
- Action = 'DB_CODE',
802
- Tags = {
803
- Status = 'DB_PREPARE_FAILED',
804
- Message = "DB PREPARED QUERY FAILED"
805
- },
806
- Data = { Code = "Failed to prepare select statement" }
807
- })
808
- print("Failed to prepare select statement")
809
- return json.encode({ Code = 'DB_PREPARE_FAILED' })
810
- end
811
-
812
- local step_status = select_stmt:step()
813
- if step_status ~= sqlite3.OK and step_status ~= sqlite3.DONE and step_status ~= sqlite3.ROW then
814
- ao.send({
815
- Target = msg.From,
816
- Action = 'DB_STEP_CODE',
817
- Tags = {
818
- Status = 'ERROR',
819
- Message = 'sqlite step error'
820
- },
821
- Data = { DB_STEP_MSG = step_status }
822
- })
823
- return json.encode({ Code = step_status })
824
- end
825
-
826
- if step_status == sqlite3.DONE then
827
- ao.send({
828
- Target = msg.From,
829
- Action = 'Read-Profile-Error',
830
- Tags = {
831
- Status = 'Error',
832
- Message = 'Profile not found'
833
- }
834
- })
835
- return
836
- end
837
-
838
- row = select_stmt:get_named_values()
839
- local metadata = {
840
- ProfileId = row.id,
841
- Username = row.username,
842
- ProfileImage = row.profile_image,
843
- CoverImage = row.cover_image,
844
- Description = row.description,
845
- DisplayName = row.display_name,
846
- DateCreated = row.date_created,
847
- DateUpdated = row.date_updated
848
- }
849
- ao.send({
850
- Target = msg.From,
851
- Action = 'Success',
852
- Tags = {
853
- Status = 'Success',
854
- Message = 'Read success'
855
- },
856
- Data = json.encode(metadata)
857
- })
858
- end)