Stiglo je novo izdanje. Osvježi stranu.
Pravo na uvid u kod. Otvoren protokol omogućava nezavisne operatere i interoperabilnost. Manifest
Izvor
4d7883a894b3
- server.js
- lib/auth.js
- lib/build.js
- lib/cards.js
- lib/db.js
- lib/gradovi.js
- lib/icons.js
- lib/imena.js
- lib/jezik.js
- lib/kartapodaci.js
- lib/lekcije.js
- lib/md.js
- lib/mehanika.js
- lib/mreza.js
- lib/pages.js
- lib/registar.js
- lib/routes.js
- lib/schema2.js
- lib/views.js
- seed/content.mjs
- seed/seed.mjs
- public/app.js
- public/style.css
1 import fs from 'node:fs';
2 import path from 'node:path';
3 import {GRADOVI} from './gradovi.js';
4 export const SCHEMA2=`
5 CREATE TABLE IF NOT EXISTS names(name TEXT PRIMARY KEY,skeleton TEXT,owner_id INTEGER,kind TEXT,net TEXT,origin TEXT,service_id TEXT,status TEXT,trust TEXT,sequence INTEGER,expires_at INTEGER,policy_version INTEGER,created_at INTEGER,updated_at INTEGER,sig TEXT,key_id TEXT);
6 CREATE TABLE IF NOT EXISTS reg_keys(key_id TEXT PRIMARY KEY,public_key TEXT,created_at INTEGER,retired_at INTEGER);
7 CREATE TABLE IF NOT EXISTS reg_log(seq INTEGER PRIMARY KEY,at INTEGER,action TEXT,name TEXT,actor_id INTEGER,payload TEXT,prev_hash TEXT,hash TEXT,sig TEXT,key_id TEXT);
8 CREATE TABLE IF NOT EXISTS approvals(id INTEGER PRIMARY KEY,subject TEXT,subject_id TEXT,steward_id INTEGER,at INTEGER,UNIQUE(subject,subject_id,steward_id));
9 CREATE TABLE IF NOT EXISTS projects(id INTEGER PRIMARY KEY,owner_id INTEGER,title TEXT,kind TEXT,summary TEXT,city_id TEXT,name TEXT,url TEXT,lang TEXT,created_at INTEGER);
10 CREATE TABLE IF NOT EXISTS pages(name TEXT PRIMARY KEY,owner_id INTEGER,title TEXT,body TEXT,published INTEGER,updated_at INTEGER);
11 CREATE TABLE IF NOT EXISTS follows(user_id INTEGER,kind TEXT,target_id TEXT,at INTEGER,PRIMARY KEY(user_id,kind,target_id));
12 CREATE TABLE IF NOT EXISTS listings(id INTEGER PRIMARY KEY,seller_id INTEGER,title TEXT,body TEXT,kind TEXT,price_eur_text TEXT,price_dinar INTEGER,stock INTEGER,status TEXT,created_at INTEGER);
13 CREATE TABLE IF NOT EXISTS orders(id INTEGER PRIMARY KEY,listing_id INTEGER,buyer_id INTEGER,seller_id INTEGER,amount INTEGER,status TEXT,created_at INTEGER,updated_at INTEGER,release_at INTEGER);
14 CREATE TABLE IF NOT EXISTS ratings(order_id INTEGER,from_id INTEGER,to_id INTEGER,score INTEGER,note TEXT,at INTEGER,PRIMARY KEY(order_id,from_id));
15 CREATE TABLE IF NOT EXISTS disputes(id INTEGER PRIMARY KEY,kind TEXT,ref TEXT,opener_id INTEGER,respondent_id INTEGER,statement TEXT,response TEXT,reviewer_id INTEGER,decision TEXT,status TEXT,deadline_at INTEGER,appeal_of INTEGER,redact INTEGER,created_at INTEGER,decided_at INTEGER);
16 CREATE TABLE IF NOT EXISTS proposals(id INTEGER PRIMARY KEY,kind TEXT,title TEXT,body TEXT,options TEXT,author_id INTEGER,thread_id INTEGER,opens_at INTEGER,closes_at INTEGER,quorum INTEGER,threshold REAL,status TEXT,result TEXT);
17 CREATE TABLE IF NOT EXISTS ballots(proposal_id INTEGER,user_id INTEGER,choice TEXT,at INTEGER,PRIMARY KEY(proposal_id,user_id));
18 CREATE TABLE IF NOT EXISTS candidates(proposal_id INTEGER,user_id INTEGER,seat TEXT,statement TEXT,PRIMARY KEY(proposal_id,user_id));
19 CREATE TABLE IF NOT EXISTS mandates(id INTEGER PRIMARY KEY,user_id INTEGER,seat TEXT,starts_at INTEGER,ends_at INTEGER,proposal_id INTEGER);
20 CREATE TABLE IF NOT EXISTS mirrors(id INTEGER PRIMARY KEY,owner_id INTEGER,url TEXT,city_id TEXT,note TEXT,created_at INTEGER,simulated INTEGER);
21 CREATE TABLE IF NOT EXISTS invites(code TEXT PRIMARY KEY,user_id INTEGER,created_at INTEGER,uses INTEGER DEFAULT 0);
22 CREATE TABLE IF NOT EXISTS returns(handle TEXT PRIMARY KEY,code_hash TEXT,member_no INTEGER,payload TEXT,expires_at INTEGER);
23 CREATE TABLE IF NOT EXISTS lesson_done(user_id INTEGER,lesson TEXT,at INTEGER,PRIMARY KEY(user_id,lesson));
24 CREATE TABLE IF NOT EXISTS counters(key TEXT,day TEXT,n INTEGER,PRIMARY KEY(key,day));
25 CREATE TABLE IF NOT EXISTS docs(slug TEXT PRIMARY KEY,title TEXT,body TEXT,version INTEGER,updated_at INTEGER);
26 CREATE TABLE IF NOT EXISTS card_instances(id INTEGER PRIMARY KEY,edition TEXT,serial INTEGER,owner_id INTEGER,minted_at INTEGER,source TEXT,sig TEXT,key_id TEXT,UNIQUE(edition,serial));
27 CREATE TABLE IF NOT EXISTS card_transfers(id INTEGER PRIMARY KEY,card_id INTEGER,from_id INTEGER,to_id INTEGER,kind TEXT,trade_id INTEGER,at INTEGER);
28 CREATE TABLE IF NOT EXISTS trades(id INTEGER PRIMARY KEY,from_id INTEGER,to_id INTEGER,give_json TEXT,want_json TEXT,dinar INTEGER,status TEXT,created_at INTEGER,decided_at INTEGER);
29 CREATE TABLE IF NOT EXISTS card_shares(token TEXT PRIMARY KEY,user_id INTEGER,fields_json TEXT,created_at INTEGER,revoked INTEGER DEFAULT 0);
30 CREATE TABLE IF NOT EXISTS name_transfers(name TEXT PRIMARY KEY,from_id INTEGER,to_id INTEGER,expires_at INTEGER);
31 CREATE TABLE IF NOT EXISTS work_submissions(id INTEGER PRIMARY KEY,user_id INTEGER,lesson INTEGER,lang TEXT,body TEXT,reviewer_id INTEGER,completed_at INTEGER,created_at INTEGER,UNIQUE(lesson,lang,user_id));
32 CREATE TABLE IF NOT EXISTS activities(id INTEGER PRIMARY KEY,user_id INTEGER,kind TEXT,ref TEXT,at INTEGER);
33 CREATE INDEX IF NOT EXISTS activity_date ON activities(at,user_id);
34 `;
35 export function migrate(db,seed) {
36 if(Number(db.meta('schema_version'))>=2)return false;
37 const hasV1=!!db.get('SELECT 1 FROM users LIMIT 1');
38 if(hasV1){const dir=path.join(db.dataDir,'backups');fs.mkdirSync(dir,{recursive:true});const f=path.join(dir,'forum-v1-final.db');if(!fs.existsSync(f))db.raw.exec(`VACUUM INTO '${f.replaceAll("'","''")}'`);}
39 db.raw.exec('PRAGMA foreign_keys=OFF');
40 try{db.tx(()=>{
41 db.raw.exec(SCHEMA2);
42 for(const [table,col,type] of [['users','city_id','TEXT'],['users','pismo',"TEXT DEFAULT 'lat'"],['users','abuse_contact',"TEXT DEFAULT ''"],['users','invited_by','INTEGER'],['threads','lang',"TEXT DEFAULT 'sh'"],['posts','lang',"TEXT DEFAULT 'sh'"]]){
43 if(!db.all(`PRAGMA table_info(${table})`).some(x=>x.name===col))db.raw.exec(`ALTER TABLE ${table} ADD COLUMN ${col} ${type}`);
44 }
45 let previousCategories=[];
46 if(hasV1){
47 previousCategories=db.all('SELECT t.id,c.slug FROM threads t JOIN categories c ON c.id=t.category_id');
48 // Real contributions survive. The permanent backup also retains the retired demonstration conversations.
49 db.run('DELETE FROM reactions WHERE post_id IN (SELECT id FROM posts WHERE user_id IN (SELECT id FROM users WHERE is_seed=1 OR is_test=1))');
50 db.run('DELETE FROM posts WHERE user_id IN (SELECT id FROM users WHERE is_seed=1 OR is_test=1)');
51 db.run('DELETE FROM threads WHERE id NOT IN (SELECT thread_id FROM posts)');
52 db.run('DELETE FROM user_cards WHERE user_id IN (SELECT id FROM users WHERE is_seed=1 OR is_test=1 OR deleted=1)');
53 for(const table of ['notifications','reports','search','thread_reads'])db.run(`DELETE FROM ${table}`);
54 db.run('DELETE FROM sessions WHERE user_id IN (SELECT id FROM users WHERE is_seed=1 OR is_test=1 OR deleted=1)');
55 db.run('DELETE FROM ledger WHERE user_id IN (SELECT id FROM users WHERE is_seed=1 OR is_test=1 OR deleted=1)');
56 db.run('DELETE FROM users WHERE is_seed=1 OR is_test=1 OR deleted=1');
57 db.run('DELETE FROM categories');
58 for(const u of db.all('SELECT id,city FROM users'))db.run('UPDATE users SET city_id=?,city=? WHERE id=?',GRADOVI.find(g=>g.ime===u.city)?.id??null,'',u.id);
59 }
60 seed();
61 if(hasV1){const admin=db.get("SELECT id FROM users WHERE handle='signal'").id,cat=db.get("SELECT id FROM categories WHERE slug='kafana'").id;
62 db.run('UPDATE threads SET user_id=? WHERE user_id NOT IN (SELECT id FROM users)',admin);
63 const renamed={'signal-desk':'oglasna-tabla',welcome:'prvi-koraci',registry:'registar',market:'pijaca',culture:'kultura',builders:'radionica',governance:'uprava'};
64 for(const prior of previousCategories){const target=db.get('SELECT id FROM categories WHERE slug=?',renamed[prior.slug]||prior.slug)?.id||cat;db.run('UPDATE threads SET category_id=? WHERE id=?',target,prior.id);}
65 db.run('UPDATE threads SET category_id=? WHERE category_id NOT IN (SELECT id FROM categories)',cat);
66 db.run('INSERT INTO search(title,body,post_id,thread_id) SELECT t.title,p.body,p.id,t.id FROM posts p JOIN threads t ON t.id=p.thread_id WHERE p.id NOT IN (SELECT post_id FROM search)');
67 }
68 db.meta('schema_version',2);
69 });}finally{db.raw.exec('PRAGMA foreign_keys=ON');}
70 return true;
71 }
72