From 047dc71eb05c0c4ee35ac579dd22344cc11fb40c Mon Sep 17 00:00:00 2001 From: 728 Date: Fri, 24 Feb 2023 15:17:06 +0800 Subject: [PATCH] 0.0.7 init #40 --- ismism.ts/.gitignore | 1 - ismism.ts/cli/dbset.ts | 38 --- ismism.ts/deno.json | 17 - ismism.ts/deno.lock | 105 ------ ismism.ts/src/db.ts | 73 ---- ismism.ts/src/eid/act.ts | 41 --- ismism.ts/src/eid/agd.ts | 74 ---- ismism.ts/src/eid/aut.ts | 39 --- ismism.ts/src/eid/id.ts | 42 --- ismism.ts/src/eid/is.ts | 118 ------- ismism.ts/src/eid/rec.ts | 86 ----- ismism.ts/src/eid/rel.ts | 47 --- ismism.ts/src/eid/soc.ts | 66 ---- ismism.ts/src/eid/typ.ts | 65 ---- ismism.ts/src/eid/usr.ts | 63 ---- ismism.ts/src/ont/adm.ts | 564 ------------------------------- ismism.ts/src/ont/base.ts | 39 --- ismism.ts/src/ont/crypt.ts | 37 -- ismism.ts/src/ont/jwt.ts | 36 -- ismism.ts/src/ont/sms.ts | 75 ---- ismism.ts/src/ont/utc.ts | 26 -- ismism.ts/src/pra/con.ts | 33 -- ismism.ts/src/pra/doc.ts | 54 --- ismism.ts/src/pra/pas.ts | 93 ----- ismism.ts/src/pra/pos.ts | 99 ------ ismism.ts/src/pra/pre.ts | 60 ---- ismism.ts/src/pra/pro.ts | 56 --- ismism.ts/src/pra/put.ts | 102 ------ ismism.ts/src/pra/que.ts | 47 --- ismism.ts/src/ser.ts | 61 ---- ismism.ts/tst/eid.test.ts | 174 ---------- ismism.ts/tst/ont.test.ts | 63 ---- ismism.ts/tst/pos.test.ts | 147 -------- ismism.ts/tst/que.test.ts | 112 ------ ismism.ts/ui/bind/article.ts | 371 -------------------- ismism.ts/ui/bind/bind.ts | 3 - ismism.ts/ui/bind/nav.ts | 47 --- ismism.ts/ui/bind/section.ts | 177 ---------- ismism.ts/ui/bind/template.ts | 121 ------- ismism.ts/ui/index/index.html | 49 --- ismism.ts/ui/index/style.css | 531 ----------------------------- ismism.ts/ui/index/template.html | 300 ---------------- ismism.ts/ui/ui.ts | 12 - 43 files changed, 4364 deletions(-) delete mode 100644 ismism.ts/cli/dbset.ts delete mode 100644 ismism.ts/deno.lock delete mode 100644 ismism.ts/src/db.ts delete mode 100644 ismism.ts/src/eid/act.ts delete mode 100644 ismism.ts/src/eid/agd.ts delete mode 100644 ismism.ts/src/eid/aut.ts delete mode 100644 ismism.ts/src/eid/id.ts delete mode 100644 ismism.ts/src/eid/is.ts delete mode 100644 ismism.ts/src/eid/rec.ts delete mode 100644 ismism.ts/src/eid/rel.ts delete mode 100644 ismism.ts/src/eid/soc.ts delete mode 100644 ismism.ts/src/eid/typ.ts delete mode 100644 ismism.ts/src/eid/usr.ts delete mode 100644 ismism.ts/src/ont/adm.ts delete mode 100644 ismism.ts/src/ont/base.ts delete mode 100644 ismism.ts/src/ont/crypt.ts delete mode 100644 ismism.ts/src/ont/jwt.ts delete mode 100644 ismism.ts/src/ont/sms.ts delete mode 100644 ismism.ts/src/ont/utc.ts delete mode 100644 ismism.ts/src/pra/con.ts delete mode 100644 ismism.ts/src/pra/doc.ts delete mode 100644 ismism.ts/src/pra/pas.ts delete mode 100644 ismism.ts/src/pra/pos.ts delete mode 100644 ismism.ts/src/pra/pre.ts delete mode 100644 ismism.ts/src/pra/pro.ts delete mode 100644 ismism.ts/src/pra/put.ts delete mode 100644 ismism.ts/src/pra/que.ts delete mode 100644 ismism.ts/src/ser.ts delete mode 100644 ismism.ts/tst/eid.test.ts delete mode 100644 ismism.ts/tst/ont.test.ts delete mode 100644 ismism.ts/tst/pos.test.ts delete mode 100644 ismism.ts/tst/que.test.ts delete mode 100644 ismism.ts/ui/bind/article.ts delete mode 100644 ismism.ts/ui/bind/bind.ts delete mode 100644 ismism.ts/ui/bind/nav.ts delete mode 100644 ismism.ts/ui/bind/section.ts delete mode 100644 ismism.ts/ui/bind/template.ts delete mode 100644 ismism.ts/ui/index/index.html delete mode 100644 ismism.ts/ui/index/style.css delete mode 100644 ismism.ts/ui/index/template.html delete mode 100644 ismism.ts/ui/ui.ts diff --git a/ismism.ts/.gitignore b/ismism.ts/.gitignore index 495f1d2..8d6b247 100644 --- a/ismism.ts/.gitignore +++ b/ismism.ts/.gitignore @@ -1,3 +1,2 @@ /cli/dbfill.ts *.js -*.pdf diff --git a/ismism.ts/cli/dbset.ts b/ismism.ts/cli/dbset.ts deleted file mode 100644 index 99cf86f..0000000 --- a/ismism.ts/cli/dbset.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { db } from "../src/db.ts" -import { act_c } from "../src/eid/act.ts" -import { aut_c } from "../src/eid/aut.ts" -import { usr_c, usr_u } from "../src/eid/usr.ts" - -await db("ismism", true) - -const actid = [ - `ismism${Math.round(Math.random() * 1000000)}`, - `ismism${Math.round(Math.random() * 1000000)}`, -] - -const [uid1] = await Promise.all([ - usr_c("11111111111", [1, 2], "江苏", "苏州"), - act_c({ - _id: actid[0], - exp: new Date("2023-06-31").getTime(), - act: "usrnbr", uid: 1 - }), - aut_c({ _id: 1, aut: ["pre_usr", "pre_soc", "pre_agd"] }) -]) -const [uid2] = await Promise.all([ - usr_c("11111111112", [1, 2], "江苏", "苏州"), - act_c({ - _id: actid[1], - exp: new Date("2023-06-31").getTime(), - act: "usrnbr", uid: 2 - }), - aut_c({ _id: 2, aut: ["pre_usr", "pre_soc", "pre_agd"] }) -]) -await Promise.all([ - usr_u(uid1!, { $set: { nam: "未明子" } }), - usr_u(uid1!, { $unset: { nbr: "" } }), - usr_u(uid2!, { $set: { nam: "张正午" } }), - usr_u(uid2!, { $unset: { nbr: "" } }), -]) - -console.log([uid1, uid2], actid) diff --git a/ismism.ts/deno.json b/ismism.ts/deno.json index b3d597e..14c2fe2 100644 --- a/ismism.ts/deno.json +++ b/ismism.ts/deno.json @@ -27,22 +27,5 @@ ], "exclude": [] } - }, - "fmt": { - "files": { - "include": [ - "src/", - "ui/", - "cli/", - "tst/" - ] - }, - "options": { - "useTabs": true, - "lineWidth": 80, - "indentWidth": 4, - "singleQuote": true, - "proseWrap": "preserve" - } } } diff --git a/ismism.ts/deno.lock b/ismism.ts/deno.lock deleted file mode 100644 index 46349bb..0000000 --- a/ismism.ts/deno.lock +++ /dev/null @@ -1,105 +0,0 @@ -{ - "version": "2", - "remote": { - "https://deno.land/std@0.154.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", - "https://deno.land/std@0.154.0/_wasm_crypto/lib/deno_std_wasm_crypto.generated.mjs": "dfcd6777d05345362c70f9f2c49abba3ed3f925fccfcf725abe2d16d51819433", - "https://deno.land/std@0.154.0/_wasm_crypto/mod.ts": "6c60d332716147ded0eece0861780678d51b560f533b27db2e15c64a4ef83665", - "https://deno.land/std@0.154.0/async/deferred.ts": "c01de44b9192359cebd3fe93273fcebf9e95110bf3360023917da9a2d1489fae", - "https://deno.land/std@0.154.0/bytes/bytes_list.ts": "aba5e2369e77d426b10af1de0dcc4531acecec27f9b9056f4f7bfbf8ac147ab4", - "https://deno.land/std@0.154.0/bytes/equals.ts": "3c3558c3ae85526f84510aa2b48ab2ad7bdd899e2e0f5b7a8ffc85acb3a6043a", - "https://deno.land/std@0.154.0/bytes/mod.ts": "763f97d33051cc3f28af1a688dfe2830841192a9fea0cbaa55f927b49d49d0bf", - "https://deno.land/std@0.154.0/crypto/_fnv/fnv32.ts": "aa9bddead8c6345087d3abd4ef35fb9655622afc333fc41fff382b36e64280b5", - "https://deno.land/std@0.154.0/crypto/_fnv/fnv64.ts": "625d7e7505b6cb2e9801b5fd6ed0a89256bac12b2bbb3e4664b85a88b0ec5bef", - "https://deno.land/std@0.154.0/crypto/_fnv/index.ts": "a8f6a361b4c6d54e5e89c16098f99b6962a1dd6ad1307dbc97fa1ecac5d7060a", - "https://deno.land/std@0.154.0/crypto/_fnv/util.ts": "4848313bed7f00f55be3cb080aa0583fc007812ba965b03e4009665bde614ce3", - "https://deno.land/std@0.154.0/crypto/keystack.ts": "e481eed28007395e554a435e880fee83a5c73b9259ed8a135a75e4b1e4f381f7", - "https://deno.land/std@0.154.0/crypto/mod.ts": "0ef11f063cd0f9759485a3c9051e15125e1bde3b47c23b47e79b6e13cfcf9481", - "https://deno.land/std@0.154.0/crypto/timing_safe_equal.ts": "82a29b737bc8932d75d7a20c404136089d5d23629e94ba14efa98a8cc066c73e", - "https://deno.land/std@0.154.0/encoding/base64.ts": "c57868ca7fa2fbe919f57f88a623ad34e3d970d675bdc1ff3a9d02bba7409db2", - "https://deno.land/std@0.154.0/encoding/base64url.ts": "a5f82a9fa703bd85a5eb8e7c1296bc6529e601ebd9642cc2b5eaa6b38fa9e05a", - "https://deno.land/std@0.154.0/encoding/hex.ts": "4cc5324417cbb4ac9b828453d35aed45b9cc29506fad658f1f138d981ae33795", - "https://deno.land/std@0.154.0/fmt/colors.ts": "ff7dc9c9f33a72bd48bc24b21bbc1b4545d8494a431f17894dbc5fe92a938fc4", - "https://deno.land/std@0.154.0/io/buffer.ts": "fae02290f52301c4e0188670e730cd902f9307fb732d79c4aa14ebdc82497289", - "https://deno.land/std@0.154.0/io/files.ts": "d199ef64e918a256320ba8d8d44ae91de87c9077df8f8d6cca013f1b9fbbe285", - "https://deno.land/std@0.154.0/io/mod.ts": "33507cf2460ab67d0d90fb5749fa6fecb33897642b49d54a6bb1ac81e4768f69", - "https://deno.land/std@0.154.0/io/readers.ts": "45847ad404afd2f605eae1cff193f223462bc55eeb9ae313c2f3db28aada0fd6", - "https://deno.land/std@0.154.0/io/streams.ts": "988a19155b52161f0035ce539e2f1d12edbc4c389fa7633da832a64e6edbe1a0", - "https://deno.land/std@0.154.0/io/types.d.ts": "0cae3a62da7a37043661746c65c021058bae020b54e50c0e774916e5d4baee43", - "https://deno.land/std@0.154.0/io/util.ts": "078da53bba767bec0d45f7da44411f6dbf269e51ef7fcfea5e3714e04681c674", - "https://deno.land/std@0.154.0/io/writers.ts": "2e1c63ffd0cfba411b1fd8374609abff9ea86187c9d4d885d42e6fc20325ef0e", - "https://deno.land/std@0.154.0/streams/conversion.ts": "fc4eb76a14148c43f0b85e903a5a1526391aa40ed9434dc21e34f88304eb823e", - "https://deno.land/std@0.154.0/testing/_diff.ts": "141f978a283defc367eeee3ff7b58aa8763cf7c8e0c585132eae614468e9d7b8", - "https://deno.land/std@0.154.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832", - "https://deno.land/std@0.154.0/testing/asserts.ts": "ac295f7fd22a7af107580e2475402a8c386cb1bf18bf837ae266ac0665786026", - "https://deno.land/std@0.173.0/encoding/base64.ts": "7de04c2f8aeeb41453b09b186480be90f2ff357613b988e99fabb91d2eeceba1", - "https://deno.land/std@0.173.0/encoding/base64url.ts": "3f1178f6446834457b16bfde8b559c1cd3481727fe384d3385e4a9995dc2d851", - "https://deno.land/std@0.173.0/encoding/hex.ts": "50f8c95b52eae24395d3dfcb5ec1ced37c5fe7610ef6fffdcc8b0fdc38e3b32f", - "https://deno.land/x/mongo@v0.31.1/deps.ts": "ba57aa94021d88959c6aac77edbbe85226e4a6836230dcdd891da63afcbf88c1", - "https://deno.land/x/mongo@v0.31.1/mod.ts": "0989f34d08c40440b8786140abdaf863e964e23df5d1a80e661d3d4170d9d21e", - "https://deno.land/x/mongo@v0.31.1/src/auth/base.ts": "7fe14cf0a63d6bbc4ba69a000a04b3b184d26842504d94652a6af2d0c9494944", - "https://deno.land/x/mongo@v0.31.1/src/auth/mod.ts": "b161611bd5be9e9d1b4497227c8ea93ad4daadcd98038c9e5a707bc5da7a25ca", - "https://deno.land/x/mongo@v0.31.1/src/auth/pbkdf2.ts": "1f1db192fd37869d118ab34780b64567ebcf0ad83a03ef28b3d740cae9adb47a", - "https://deno.land/x/mongo@v0.31.1/src/auth/scram.ts": "187db02e94e7e5423ec902e87d6839028770dca57830dca7f154dcd22a959c0f", - "https://deno.land/x/mongo@v0.31.1/src/auth/x509.ts": "a75b27c549707dd441434ae400a3e6a24da7fe7d4e0e80c9bb79dfc6426b651e", - "https://deno.land/x/mongo@v0.31.1/src/client.ts": "368cac10b3df3bfbc2dfba468d1bbd1332c359a643e0bb81a13d7220a58b43ff", - "https://deno.land/x/mongo@v0.31.1/src/cluster.ts": "cff69bf284a5c7fcaff231494f1ab56ca652e725e58622723e402fbb61448d0e", - "https://deno.land/x/mongo@v0.31.1/src/collection/collection.ts": "b8227c276633d2e6425736d5f5c5d5411deed3bc7bf2fccf36e39d609d5b1cb5", - "https://deno.land/x/mongo@v0.31.1/src/collection/commands/aggregate.ts": "440906a670adb46edb36fd95573ffa83f192775108b621520be992165910e895", - "https://deno.land/x/mongo@v0.31.1/src/collection/commands/find.ts": "5c3b750d8c82ce08d865a381bc71f600406cbc4912c4aa689238755579fb71f8", - "https://deno.land/x/mongo@v0.31.1/src/collection/commands/list_indexes.ts": "d32a5120305d0547497026b4f5ab2ecc2f40ff7f44c405b99c2a0287765333f5", - "https://deno.land/x/mongo@v0.31.1/src/collection/commands/update.ts": "cf352108a5dd34f0928c2196a432383d366b8ed292676c71358b9ecf1289418d", - "https://deno.land/x/mongo@v0.31.1/src/collection/mod.ts": "bd791a0b9b46be4365f88c54893584eadec2f8cd799db9eb05e0b5b4c8d72b8e", - "https://deno.land/x/mongo@v0.31.1/src/database.ts": "6effe102726693d2ed6817973facfbc82ae2b1ac68efddbf54493df7e29e105c", - "https://deno.land/x/mongo@v0.31.1/src/error.ts": "8180a822b0831a94a6a28815865b5b40e3996220684bea60fcb81b272ddd06eb", - "https://deno.land/x/mongo@v0.31.1/src/gridfs/bucket.ts": "a4452d63f6928f57486a214a499b54b80b98cc0d13e3d85a6841b34d5ff12a61", - "https://deno.land/x/mongo@v0.31.1/src/gridfs/indexes.ts": "c9747d8272c65399a6364e08071bd1b5ac9c10816329aa670d7b6b9e895ffb5a", - "https://deno.land/x/mongo@v0.31.1/src/gridfs/upload.ts": "6a54a21b00c6f22ad0da6ceef7a2932dc600560f594c2551abd8e4a64976abae", - "https://deno.land/x/mongo@v0.31.1/src/protocol/cursor.ts": "c370a28856fa236129cc2d7abf7ebc4ac6cdd60acb93e0e7371433f7332394cb", - "https://deno.land/x/mongo@v0.31.1/src/protocol/handshake.ts": "3c3ba547d5322751b9756ce9a4750f3cf18febee0a64edca5b007634bd80e0fe", - "https://deno.land/x/mongo@v0.31.1/src/protocol/header.ts": "0f28db842f886e57b7013606c1391affab2e2960a1a4568d2502e7b788117716", - "https://deno.land/x/mongo@v0.31.1/src/protocol/message.ts": "b1121b98420c9a44783619c7a0b2f7bb2cb305dfc64adc3e6a9b7781f4d35a3a", - "https://deno.land/x/mongo@v0.31.1/src/protocol/mod.ts": "4e24d563049c0a236234598ca786ca13778dc17fdb80ac543ac6c75d0c5094d7", - "https://deno.land/x/mongo@v0.31.1/src/protocol/protocol.ts": "92568dd86e6ef3f54054113d9f5620f158fc1dfee2a7c9d13623975835d5996a", - "https://deno.land/x/mongo@v0.31.1/src/types.ts": "aae7d0053341d26a802de9ac26a5209a67f53052bc2c13fae018396867590d4c", - "https://deno.land/x/mongo@v0.31.1/src/types/geojson.ts": "14690e2fa1591939253ddc9de181b0664051e9462db131b72be5fb9d064dff44", - "https://deno.land/x/mongo@v0.31.1/src/types/geospatial.ts": "c73ee13536365fa5d868b65ab47b3488a5f223a67e1e059761886f750db70ef9", - "https://deno.land/x/mongo@v0.31.1/src/types/gridfs.ts": "e1fd12c3ca58d437267e7a8557d745d23b9d8916d1da34c1847e5e373728dfa0", - "https://deno.land/x/mongo@v0.31.1/src/types/read_write_concern.ts": "d00f35eb85520e776741888685d08d479766a19e9a0a970b53f4594c9db00496", - "https://deno.land/x/mongo@v0.31.1/src/utils/ns.ts": "fb0c57b8dc4d31f8993112d267dec3c163d3e8862198d1cd03b2b51bcc3caad9", - "https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/deps.ts": "95ceb81b353110526dacf2a98854bc79d6e17d7f173af8806e91c05555d7b8c7", - "https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/load_code_points.ts": "f6a4ef2eb2345eac40ffbf1a30661cca803f399865f2a0fadafb71f57d4c97bf", - "https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/memory_pager.ts": "f55a79a13ec569c21630c3915a9af0c6fc0aa2b899121fa2a85a813c6dd4afba", - "https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/mod.ts": "0a8a39a0784d065a79c54ce63d7d7b103d0b94addc5b7bcf985517ba2442c8a1", - "https://deno.land/x/mongo@v0.31.1/src/utils/saslprep/sparse_bitfield.ts": "07d6fe2ecd4ba5f711c44c1ae409bb9c1fe3a3cfc09e27434d231d4aae46dd2d", - "https://deno.land/x/mongo@v0.31.1/src/utils/srv.ts": "ed5f78ffe6480faac68291a87e51e3674eff5f28aec937ee97248e99e1317b16", - "https://deno.land/x/mongo@v0.31.1/src/utils/uri.ts": "dcfab8e1dcfcc875c75ada1d9f366664480c03b65594990d6342ed88925452e5", - "https://deno.land/x/web_bson@v0.2.5/deps.ts": "b113dd66321c328ae90b7cf8f0f6b37ea472f6f5a5a0553f0c7dfd89538d2748", - "https://deno.land/x/web_bson@v0.2.5/mod.ts": "a2b58ed2e1748e6faa56fbe6caf0e1937f4e77de15376cad920aea655b17bcf3", - "https://deno.land/x/web_bson@v0.2.5/src/binary.ts": "2bd89fca666d06b12e4da7ae2aae2b87e495666e002011ceef4fd3e228ea3018", - "https://deno.land/x/web_bson@v0.2.5/src/bson.ts": "608b1b8e1b9a2abcb2d3b601b63e2731608a2ee0941e801a08c1328a37ff0751", - "https://deno.land/x/web_bson@v0.2.5/src/code.ts": "ad713ab49d2c9028fa798630ccdf345a9a2fbaa468c9bd0c3df3f411c3679bd1", - "https://deno.land/x/web_bson@v0.2.5/src/constants.ts": "906fb45165e2df04332ffeb6a407b39d257b76ad64667ecfe4848bfc64934a5e", - "https://deno.land/x/web_bson@v0.2.5/src/db_ref.ts": "2b29a4b74fde79d25322f31f8b98a908270468fa84af7ebd72c1e45b436b9fe2", - "https://deno.land/x/web_bson@v0.2.5/src/decimal128.ts": "f0377c29b255ec423d4b491675dfb83410d5e92a9fcca9bcd63bfd757489b05d", - "https://deno.land/x/web_bson@v0.2.5/src/double.ts": "9df7baf7cdb2d8ef50a141a373c755cabebeb5a5da6c2f551e5377064ccf2aa9", - "https://deno.land/x/web_bson@v0.2.5/src/error.ts": "d7aa0d57de5c6dc137402fc97219b6e136fc2dcddef90f031bdeb52181cc5275", - "https://deno.land/x/web_bson@v0.2.5/src/extended_json.ts": "98f57fba581712e49060ed5d495c3d1b8be557dc61b11588ba79882faad4b289", - "https://deno.land/x/web_bson@v0.2.5/src/float_parser.ts": "bffe91eae89d9d177a88d795981681ecf05850facfb92da93901576a268235cd", - "https://deno.land/x/web_bson@v0.2.5/src/int_32.ts": "8ac60fd82c34b62645f60b2eb45238391a3e0994980dced75b31f97058cbb3b4", - "https://deno.land/x/web_bson@v0.2.5/src/long.ts": "efffd2eb49afd7161452f8f3533d46aad78c9af6b07f6474c8c937a1b53c5d19", - "https://deno.land/x/web_bson@v0.2.5/src/max_key.ts": "8016a701657be73fd4d3b80c746084ba18322bb39bdc4e78e35f0e2f21be2a70", - "https://deno.land/x/web_bson@v0.2.5/src/min_key.ts": "19691f520868996bd2fc96bf26037badf6d32f8702c035e0d8531b549ef9854c", - "https://deno.land/x/web_bson@v0.2.5/src/objectid.ts": "afc51f3bf9d566fa474c96a8ec0362951ff962a4b8c7ecde51e4537fe95be089", - "https://deno.land/x/web_bson@v0.2.5/src/parser/calculate_size.ts": "ca1e81c793860c9200a3c6cfec220539524f81acca0d76738426bbf8ef857950", - "https://deno.land/x/web_bson@v0.2.5/src/parser/deserializer.ts": "40d154d44f80250dfef0121c1c1a997220a38d08c0fc369247f573ef83649802", - "https://deno.land/x/web_bson@v0.2.5/src/parser/serializer.ts": "fdea917596143694eda0059b0f72fdbe72ade0591c6ba4b4e8f82958ab35c37d", - "https://deno.land/x/web_bson@v0.2.5/src/parser/utils.ts": "7bfe19aaf71164d8326f82c1e01dabe6140c18939f4bd8961380495a7c76f57f", - "https://deno.land/x/web_bson@v0.2.5/src/regexp.ts": "1e287a7ada20a0a4b625bf3c191295db149bfefac6beb707fe52d0232c612265", - "https://deno.land/x/web_bson@v0.2.5/src/symbol.ts": "b727698ed367d426b32f068c067ccd43a458347589715dd329b82caf10b9cf32", - "https://deno.land/x/web_bson@v0.2.5/src/timestamp.ts": "49bba69e2a26cfea5870b69c739cbfce64814b21682ed3161105737f3d97ef66", - "https://deno.land/x/web_bson@v0.2.5/src/uuid.ts": "c8c51a946dc8c1d6a15370d50de2247f4fbf69ce1c413ae29c8e211738ec0efc", - "https://deno.land/x/web_bson@v0.2.5/src/uuid_utils.ts": "322cbea409a32cfdbffcae854b91bb30b80730741e032b98f5d6868ad63bc07d", - "https://deno.land/x/web_bson@v0.2.5/src/validate_utf8.ts": "b7f4d723c379fb66aa84e148bb59f78f4e1c96847e28c38ee7f9f3bf35703ae4", - "https://deno.land/x/web_bson@v0.2.5/utils.ts": "4c51c0be4bbb77c1e547eeef9b5aa53ffa611f628684875375103f627649ceb1" - } -} diff --git a/ismism.ts/src/db.ts b/ismism.ts/src/db.ts deleted file mode 100644 index 42c807c..0000000 --- a/ismism.ts/src/db.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Act, Agd, Aut, Fund, Soc, Usr, Work } from "./eid/typ.ts" -import { MongoClient, UpdateFilter } from "https://deno.land/x/mongo@v0.31.1/mod.ts" - -const conn = new MongoClient() -await conn.connect("mongodb://127.0.0.1:27017") - -export async function db( - nam: "ismism" | "tst", - reset = false, -) { - const db = conn.database(nam) - - const c = { - usr: db.collection("usr"), - soc: db.collection("soc"), - agd: db.collection("agd"), - - work: db.collection("work"), - fund: db.collection("fund"), - - act: db.collection("act"), - aut: db.collection("aut"), - } - - if (reset) { - await db.dropDatabase() - c.usr.createIndexes({ - indexes: [{ - key: { nam: 1 }, name: "nam", unique: true, - }, { - key: { nbr: 1 }, name: "nbr", unique: true, - partialFilterExpression: { nbr: { $exists: true } }, - }] - }) - await Promise.all([c.soc, c.agd].map(cl => cl.createIndexes({ - indexes: [{ - key: { nam: 1 }, name: "nam", unique: true, - }, { - key: { sec: 1 }, name: "sec", - }, { - key: { res: 1 }, name: "res", - }, { - key: { uid: 1 }, name: "uid", - }, { - key: { adm1: 1 }, name: "adm1", - }, { - key: { adm2: 1 }, name: "adm2", - }] - }))) - await Promise.all([c.work, c.fund].map(cl => cl.createIndexes({ - indexes: [{ - key: { "_id.aid": 1, "_id.utc": -1 }, name: "aid-utc" - }, { - key: { "_id.uid": 1, "_id.utc": -1 }, name: "uid-utc" - }, { - key: { "_id.utc": -1 }, name: "utc" - }] - }))) - } - - if (nam === "tst") coll = c - return c -} - -export let coll = await db("ismism") -export type Coll = typeof coll - -export type Update = UpdateFilter - -export type DocC<_Id> = Promise | null> -export type DocR = Promise | null> -export type DocU = Promise<0 | 1 | null> -export type DocD = Promise<0 | 1 | null> diff --git a/ismism.ts/src/eid/act.ts b/ismism.ts/src/eid/act.ts deleted file mode 100644 index 24441e3..0000000 --- a/ismism.ts/src/eid/act.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { not_actid } from "./is.ts" -import { Act } from "./typ.ts" - -export async function act_c( - act: Act, -): DocC { - if (not_actid(act._id)) return null - try { return await coll.act.insertOne(act) as Act["_id"] } - catch { return null } -} - -export async function act_r( - _id: Act["_id"] -): DocR { - if (not_actid(_id)) return null - const a = await coll.act.findOne({ _id }) - if (a && a.exp > Date.now()) return a - return null -} - -export async function act_u( - _id: Act["_id"], - u: Update, -): DocU { - if (not_actid(_id)) return null - try { - const { modifiedCount } = await coll.act.updateOne({ _id }, u) - return modifiedCount > 0 ? 1 : 0 - } catch { return null } -} - -export async function act_d( - _id: Act["_id"] -): DocD { - if (not_actid(_id)) return null - try { - const d = await coll.act.deleteOne({ _id }) - return d > 0 ? 1 : 0 - } catch { return null } -} diff --git a/ismism.ts/src/eid/agd.ts b/ismism.ts/src/eid/agd.ts deleted file mode 100644 index 09f3eb0..0000000 --- a/ismism.ts/src/eid/agd.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { not_adm } from "../ont/adm.ts" -import { not_nam, not_id, not_intro, lim_res_def, lim_uid_def, not_idl, lim_re, lim_sec, not_lim, lim_res_max, lim_uid_max, not_goal, not_img } from "./is.ts" -import { Agd } from "./typ.ts" - -export async function agd_c( - nam: Agd["nam"], - ref: Agd["ref"][0], - adm1: string, - adm2: string, -): DocC { - if (not_nam(nam) || not_id(ref) || not_adm([adm1, adm2])) return null - const l = await coll.agd.findOne({}, { projection: { _id: 1 }, sort: { _id: -1 } }) - const _id = l ? l._id + 1 : 1 - const a: Agd = { - _id, nam, rej: [], ref: [ref], - utc: Date.now(), adm1, adm2, intro: "", - sec: [], - reslim: lim_res_def, res: [], - uidlim: lim_uid_def, uid: [], - account: "", - budget: 0, fund: 0, expense: 0, - goal: [], img: [], - } - try { return await coll.agd.insertOne(a) as Agd["_id"] } - catch { return null } -} - -export async function agd_r< - P extends keyof Agd ->( - aid: Agd["_id"], - projection: Partial<{ [K in P]: 1 }> -): DocR> { - if (not_id(aid)) return null - return await coll.agd.findOne({ _id: aid }, { projection }) ?? null -} - -export async function agd_u( - _id: Agd["_id"], - u: Update, -): DocU { - if (not_id(_id)) return null - if ("$set" in u && u.$set) { - const s = u.$set - if (s.nam && not_nam(s.nam)) return null - if (s.rej && not_idl(s.rej, lim_re) || s.ref && not_idl(s.ref, lim_re)) return null - if ((s.adm1 || s.adm2) && not_adm([s.adm1, s.adm2])) return null - if (s.intro && not_intro(s.intro)) return null - if (s.sec && not_idl(s.sec, lim_sec)) return null - if (s.reslim && not_lim(s.reslim, lim_res_max)) return null - if (s.uidlim && not_lim(s.uidlim, lim_uid_max)) return null - if (s.uid && not_idl(s.uid, s.uidlim ?? lim_uid_max)) return null - if (s.budget && s.budget < 0) return null - if (s.fund && s.fund < 0) return null - if (s.expense && s.expense < 0) return null - if (s.goal && s.goal.some(not_goal)) return null - if (s.img && s.img.some(not_img)) return null - } - try { - const { modifiedCount } = await coll.agd.updateOne({ _id }, u) - return modifiedCount > 0 ? 1 : 0 - } catch { return null } -} - -export async function agd_d( - aid: Agd["_id"] -): DocD { - if (not_id(aid)) return null - try { - const c = await coll.agd.deleteOne({ _id: aid }) - return c > 0 ? 1 : 0 - } catch { return null } -} diff --git a/ismism.ts/src/eid/aut.ts b/ismism.ts/src/eid/aut.ts deleted file mode 100644 index b68ec48..0000000 --- a/ismism.ts/src/eid/aut.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { Aut } from "./typ.ts" -import { not_id } from "./is.ts" - -export async function aut_c( - aut: Aut, -): DocC { - if (not_id(aut._id)) return null - try { return await coll.aut.insertOne(aut) as Aut["_id"] } - catch { return null } -} - -export async function aut_r( - _id: Aut["_id"] -): DocR { - if (not_id(_id)) return null - return await coll.aut.findOne({ _id }) ?? null -} - -export async function aut_u( - _id: Aut["_id"], - u: Update, -): DocU { - if (not_id(_id)) return null - try { - const { modifiedCount } = await coll.aut.updateOne({ _id }, u) - return modifiedCount > 0 ? 1 : 0 - } catch { return null } -} - -export async function aut_d( - _id: Aut["_id"] -): DocD { - if (not_id(_id)) return null - try { - const d = await coll.aut.deleteOne({ _id }) - return d > 0 ? 1 : 0 - } catch { return null } -} diff --git a/ismism.ts/src/eid/id.ts b/ismism.ts/src/eid/id.ts deleted file mode 100644 index f1730b9..0000000 --- a/ismism.ts/src/eid/id.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Coll } from "../db.ts" -import { not_adm1, not_adm2 } from "../ont/adm.ts" -import { is_id } from "./is.ts" -import { Id } from "./typ.ts" - -export async function idnam( - c: Coll["usr" | "soc" | "agd"], - id: Id["_id"][], -): Promise<[Id["_id"], Id["nam"]][]> { - id = [...new Set(id.filter(is_id))] - const d = await c.find( - { _id: { $in: id } }, - { projection: { _id: 1, nam: 1 } } - ).toArray() - return d.map(d => [d._id, d.nam]) -} - -export async function id_of_adm( - c: Coll["soc" | "agd"], - adm?: { adm1: string } | { adm2: string }, -): Promise { - if (adm && "adm2" in adm && not_adm2(adm.adm2)) return [] - if (adm && "adm1" in adm && not_adm1(adm.adm1)) return [] - const d = await c.find(adm, { projection: { _id: 1 }, sort: { _id: -1 } }).toArray() - return d.map(d => d._id) -} - -export async function nid_of_adm< - A extends "adm1" | "adm2" ->( - c: Coll["soc" | "agd"], - a: A, -): Promise<[Id[A], number][]> { - const d = await c.aggregate<{ - _id: Id[A], nid: number - }>([{ - $group: { _id: `$${a}`, nid: { $count: {} } }, - }, { - $sort: { nid: -1 }, - }]).toArray() - return d.map(d => [d._id, d.nid]) -} diff --git a/ismism.ts/src/eid/is.ts b/ismism.ts/src/eid/is.ts deleted file mode 100644 index 48c8f63..0000000 --- a/ismism.ts/src/eid/is.ts +++ /dev/null @@ -1,118 +0,0 @@ -import type { Act, Agd, Id, Rec } from "./typ.ts" - -export const req_rej = 2 -export const req_ref = 2 - -export const lim_intro = 2048 -export const lim_re = 16 -export const lim_sec = 16 -export const lim_res_def = 0 -export const lim_res_max = 16 -export const lim_uid_def = 64 -export const lim_uid_max = 256 -export const lim_goal = 9 -export const lim_url = 256 -export const lim_msg = 256 - -export function is_lim( - n: number, - lim: number, -) { - return 0 <= n && n <= lim -} -export function not_lim( - n: number, - lim: number, -) { - return !is_lim(n, lim) -} - -export function is_id( - id?: null | Id["_id"] -): id is Id["_id"] { - return typeof id === "number" && id > 0 -} -export function not_id( - id?: null | Id["_id"] -) { - return !is_id(id) -} - -export function is_idl( - id: Id["_id"][], - lim: number, -) { - return id.length <= lim && id.every(is_id) -} -export function not_idl( - id: Id["_id"][], - lim: number, -) { - return !is_idl(id, lim) -} - -export function is_nam( - nam?: null | Id["nam"] -): nam is Id["nam"] { - return typeof nam === "string" && /^[\u4E00-\u9FFF]{2,16}$/.test(nam) -} -export function not_nam( - nam?: null | Id["nam"] -) { - return !is_nam(nam) -} - -export function is_nbr( - nbr?: null | string -): nbr is string { - return typeof nbr === "string" && /^1\d{10}$/.test(nbr) -} -export function not_nbr( - nbr?: null | string -) { - return !is_nbr(nbr) -} - -export function is_intro( - intro?: null | Id["intro"] -): intro is Id["intro"] { - return typeof intro === "string" && intro.length <= lim_intro -} -export function not_intro( - intro?: null | Id["intro"] -) { - return !is_intro(intro) -} - -export function not_goal( - g: Agd["goal"][0] -) { - return not_nam(g.nam) || typeof g.pct !== "number" || not_lim(g.pct, 100) -} -export function not_img( - i: Agd["img"][0] -) { - return typeof i.nam !== "string" || typeof i.src !== "string" -} - -export function is_recid( - id: Rec["_id"] -): id is Rec["_id"] { - return Object.keys(id).length === 3 && is_id(id.uid) && is_id(id.aid) && id.utc > 0 -} -export function not_recid( - id: Rec["_id"] -) { - return !is_recid(id) -} - -export function is_actid( - id: Act["_id"] -): id is Act["_id"] { - return 6 <= id.length && id.length <= 64 -} -export function not_actid( - id: Act["_id"] -) { - return !is_actid(id) -} diff --git a/ismism.ts/src/eid/rec.ts b/ismism.ts/src/eid/rec.ts deleted file mode 100644 index bf0ce0b..0000000 --- a/ismism.ts/src/eid/rec.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { coll, Coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { Agd, Fund, Rec, Usr, Work } from "./typ.ts" -import { is_id, not_id, not_rec, not_recid } from "./is.ts" - -type RecD = C extends Coll["work"] ? Work : Fund - -export function collrec( - c: "work" | "fund" | string -) { - switch (c) { - case "work": return coll.work - case "fund": return coll.fund - } - return null -} - -export async function rec_c< - C extends Coll["work" | "fund"] ->( - c: C, - r: RecD, -): DocC { - if (not_rec(r)) return null - // deno-lint-ignore no-explicit-any - try { return await c.insertOne(r as any) as Rec["_id"] } - catch { return null } -} - -export async function rec_r< - C extends Coll["work" | "fund"] ->( - c: C, - utc: number, - id?: { "_id.aid": Agd["_id"] } | { "_id.uid": Usr["_id"] }, -): DocR[]> { - if (id && ("_id.aid" in id && not_id(id["_id.aid"]) || "_id.uid" in id && not_id(id["_id.uid"]))) return null - const f = { - ...id ? id : {}, - ...utc > 0 ? { "_id.utc": { $gt: utc } } : {}, - // deno-lint-ignore no-explicit-any - } as any - return await c.find(f, { sort: { utc: -1 }, limit: 16 }).toArray() as RecD[] -} - -export async function rec_u< - C extends Coll["work" | "fund"] ->( - c: C, - _id: Rec["_id"], - u: Update>, -): DocU { - if (not_recid(_id)) return null - try { - const { modifiedCount } = await c.updateOne({ _id }, u) - return modifiedCount > 0 ? 1 : 0 - } catch { return null } -} - -export async function rec_d( - c: Coll["work" | "fund"], - _id: Rec["_id"], -): DocD { - if (not_recid(_id)) return null - try { - const d = await c.deleteOne({ _id }) - return d > 0 ? 1 : 0 - } catch { return null } -} - -export async function nrec( - id?: { aid: Agd["_id"] } | { uid: Usr["_id"][] }, -): DocR<{ work: number, fund: number }> { - let p = null - const crec = [coll.work, coll.fund] - if (id) { - if ("aid" in id) { - if (not_id(id.aid)) return null - p = crec.map(c => c.countDocuments({ "_id.aid": id.aid })) - } else if ("uid" in id) { - const uid = id.uid.filter(is_id) - p = crec.map(c => c.countDocuments({ "_id.uid": { $in: uid } })) - } else return null - } else p = crec.map(c => c.estimatedDocumentCount()) - const [work, fund] = await Promise.all(p) - return { work, fund } -} diff --git a/ismism.ts/src/eid/rel.ts b/ismism.ts/src/eid/rel.ts deleted file mode 100644 index bbf7c47..0000000 --- a/ismism.ts/src/eid/rel.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Coll, DocR } from "../db.ts" -import { not_id, req_ref } from "./is.ts" -import { Id, Usr } from "./typ.ts" -import { usr_r } from "./usr.ts" - -export type Rol = { - sec: Id["_id"][], - res: Id["_id"][], - uid: Id["_id"][], -} -export async function rol( - c: Coll["soc" | "agd"], - _id: Usr["_id"], -): DocR { - const r = await rolref(c, _id) - if (!r) return null - return { - sec: r.sec.filter(p => p[1] >= req_ref).map(p => p[0]), - res: r.res.filter(p => p[1] >= req_ref).map(p => p[0]), - uid: r.uid.filter(p => p[1] >= req_ref).map(p => p[0]), - } -} - -export type RolRef = { - sec: [Id["_id"], number][], - res: [Id["_id"], number][], - uid: [Id["_id"], number][], -} -export async function rolref( - c: Coll["soc" | "agd"], - _id: Usr["_id"], -): DocR { - if (not_id(_id)) return null - const [u, sec, res, uid] = await Promise.all([ - usr_r({ _id }, { ref: 1 }), - // deno-lint-ignore no-explicit-any - c.find({ sec: _id } as any, { projection: { _id: 1, ref: 1 } }).toArray(), - // deno-lint-ignore no-explicit-any - c.find({ res: _id } as any, { projection: { _id: 1, ref: 1 } }).toArray(), - // deno-lint-ignore no-explicit-any - c.find({ uid: _id } as any, { projection: { _id: 1, ref: 1 } }).toArray(), - ]) - if (!u) return null - const nref = (u: Usr["ref"], id: Id["ref"]) => u.filter(r => id.includes(r)).length - const f = (r: Id) => [r._id, nref(u.ref, r.ref)] as [Id["_id"], number] - return { sec: sec.map(f), res: res.map(f), uid: uid.map(f) } -} diff --git a/ismism.ts/src/eid/soc.ts b/ismism.ts/src/eid/soc.ts deleted file mode 100644 index 4869e1e..0000000 --- a/ismism.ts/src/eid/soc.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { not_adm } from "../ont/adm.ts" -import { Soc } from "./typ.ts" -import { not_nam, not_id, not_intro, lim_res_def, lim_uid_def, not_idl, lim_re, lim_sec, lim_res_max, lim_uid_max, not_lim } from "./is.ts" - -export async function soc_c( - nam: Soc["nam"], - ref: Soc["ref"][0], - adm1: string, - adm2: string, -): DocC { - if (not_nam(nam) || not_id(ref) || not_adm([adm1, adm2])) return null - const l = await coll.soc.findOne({}, { projection: { _id: 1 }, sort: { _id: -1 } }) - const _id = l ? l._id + 1 : 1 - const s: Soc = { - _id, nam, rej: [], ref: [ref], - utc: Date.now(), adm1, adm2, intro: "", - sec: [], - reslim: lim_res_def, res: [], - uidlim: lim_uid_def, uid: [], - } - try { return await coll.soc.insertOne(s) as Soc["_id"] } - catch { return null } -} - -export async function soc_r< - P extends keyof Soc ->( - sid: Soc["_id"], - projection: Partial<{ [K in P]: 1 }>, -): DocR> { - if (not_id(sid)) return null - return await coll.soc.findOne({ _id: sid }, { projection }) ?? null -} - -export async function soc_u( - _id: Soc["_id"], - u: Update, -): DocU { - if (not_id(_id)) return null - if ("$set" in u && u.$set) { - const s = u.$set - if (s.nam && not_nam(s.nam)) return null - if (s.rej && not_idl(s.rej, lim_re) || s.ref && not_idl(s.ref, lim_re)) return null - if ((s.adm1 || s.adm2) && not_adm([s.adm1, s.adm2])) return null - if (s.intro && not_intro(s.intro)) return null - if (s.sec && not_idl(s.sec, lim_sec)) return null - if (s.reslim && not_lim(s.reslim, lim_res_max)) return null - if (s.uidlim && not_lim(s.uidlim, lim_uid_max)) return null - if (s.uid && not_idl(s.uid, s.uidlim ?? lim_uid_max)) return null - } - try { - const { modifiedCount } = await coll.soc.updateOne({ _id }, u) - return modifiedCount > 0 ? 1 : 0 - } catch { return null } -} - -export async function soc_d( - sid: Soc["_id"] -): DocD { - if (not_id(sid)) return null - try { - const c = await coll.soc.deleteOne({ _id: sid }) - return c > 0 ? 1 : 0 - } catch { return null } -} diff --git a/ismism.ts/src/eid/typ.ts b/ismism.ts/src/eid/typ.ts deleted file mode 100644 index 7704d3f..0000000 --- a/ismism.ts/src/eid/typ.ts +++ /dev/null @@ -1,65 +0,0 @@ -export type Id = { - _id: number, - nam: string, - utc: number, - adm1: string, - adm2: string, - intro: string, -} -export type Re = { - rej: Usr["_id"][], - ref: Usr["_id"][], -} -export type Rel = { - sec: Usr["_id"][], - uidlim: number, - uid: Usr["_id"][], - reslim: number, - res: Usr["_id"][], -} - -export type Usr = Id & Re & { - nbr?: string, - pcode?: { code: number, utc: number }, - ptoken?: string, -} -export type Soc = Id & Re & Rel -export type Agd = Id & Re & Rel & { - account: string, - budget: number, - fund: number, - expense: number, - goal: { nam: string, pct: number }[], - img: { nam: string, src: string }[], -} - -export type Rec = { - _id: { uid: Usr["_id"], aid: Agd["_id"], utc: number }, -} -export type Work = Rec & Re & ({ - work: "work", - msg: string, -} | { - work: "video", - nam: string, - src: string, -}) -export type Fund = Rec & { - fund: number, - msg: string, -} - -export type Aut = { - _id: Usr["_id"], -} -export type Act = { - _id: string, - exp: number, -} & ({ - act: "usrfund", - ref: Usr["_id"][], - aid: Agd["_id"], -} | { - act: "usrnbr", - uid: number, -}) diff --git a/ismism.ts/src/eid/usr.ts b/ismism.ts/src/eid/usr.ts deleted file mode 100644 index d397237..0000000 --- a/ismism.ts/src/eid/usr.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Usr } from "./typ.ts" -import { coll, DocC, DocD, DocR, DocU, Update } from "../db.ts" -import { not_adm } from "../ont/adm.ts" -import { is_id, not_id, not_nam, is_nbr, not_nbr, not_intro } from "./is.ts" - -export async function usr_c( - nbr: NonNullable, - ref: Usr["ref"], - adm1: Usr["adm1"], - adm2: Usr["adm2"], -): DocC { - if (not_nbr(nbr) || ref.some(not_id) || not_adm([adm1, adm2])) return null - const l = await coll.usr.findOne({}, { projection: { _id: 1 }, sort: { _id: -1 } }) - const _id = l ? l._id + 1 : 1 - const u: Usr = { - _id, nbr, ref, adm1, adm2, - rej: [], - nam: `${_id}`, - utc: Date.now(), - intro: "", - } - try { return await coll.usr.insertOne(u) as Usr["_id"] } - catch { return null } -} - -export async function usr_r< - P extends keyof Usr ->( - f: { _id: Usr["_id"] } | { nbr: NonNullable }, - projection: Partial<{ [K in P]: 1 }> -): DocR> { - if (!("_id" in f && is_id(f._id) || "nbr" in f && is_nbr(f.nbr))) return null - return await coll.usr.findOne(f, { projection }) ?? null -} - -export async function usr_u( - _id: Usr["_id"], - u: Update, -): DocU { - if (not_id(_id)) return null - if ("$set" in u && u.$set) { - if (u.$set.nbr && not_nbr(u.$set.nbr)) return null - if (u.$set.nam && not_nam(u.$set.nam)) return null - if (u.$set.ref && u.$set.ref.some(not_id)) return null - if ((u.$set.adm1 || u.adm2) && not_adm([u.$set.adm1, u.$set.adm2])) return null - if (u.$set.intro && not_intro(u.$set.intro)) return null - } - try { - const { matchedCount, modifiedCount } = await coll.usr.updateOne({ _id }, u) - if (matchedCount > 0) return modifiedCount > 0 ? 1 : 0 - else return null - } catch { return null } -} - -export async function usr_d( - uid: Usr["_id"] -): DocD { - if (not_id(uid)) return null - try { - const c = await coll.usr.deleteOne({ _id: uid }) - return c > 0 ? 1 : 0 - } catch { return null } -} diff --git a/ismism.ts/src/ont/adm.ts b/ismism.ts/src/ont/adm.ts deleted file mode 100644 index 3b390b3..0000000 --- a/ismism.ts/src/ont/adm.ts +++ /dev/null @@ -1,564 +0,0 @@ -export const adm = new Map([ - [ - "北京", - [ - "北京" - ] - ], - [ - "天津", - [ - "天津" - ] - ], - [ - "河北", - [ - "石家庄", - "唐山", - "秦皇岛", - "邯郸", - "邢台", - "保定", - "张家口", - "承德", - "沧州", - "廊坊", - "衡水" - ] - ], - [ - "山西", - [ - "太原", - "大同", - "阳泉", - "长治", - "晋城", - "朔州", - "晋中", - "运城", - "忻州", - "临汾", - "吕梁" - ] - ], - [ - "内蒙古", - [ - "呼和浩特", - "包头", - "乌海", - "赤峰", - "通辽", - "鄂尔多斯", - "呼伦贝尔", - "巴彦淖尔", - "乌兰察布", - "兴安盟", - "锡林郭勒盟", - "阿拉善盟" - ] - ], - [ - "辽宁", - [ - "沈阳", - "大连", - "鞍山", - "抚顺", - "本溪", - "丹东", - "锦州", - "营口", - "阜新", - "辽阳", - "盘锦", - "铁岭", - "朝阳", - "葫芦岛" - ] - ], - [ - "吉林", - [ - "长春", - "吉林", - "四平", - "辽源", - "通化", - "白山", - "松原", - "白城", - "延边" - ] - ], - [ - "黑龙江", - [ - "哈尔滨", - "齐齐哈尔", - "鸡西", - "鹤岗", - "双鸭山", - "大庆", - "伊春", - "佳木斯", - "七台河", - "牡丹江", - "黑河", - "绥化", - "大兴安岭" - ] - ], - [ - "上海", - [ - "上海" - ] - ], - [ - "江苏", - [ - "南京", - "无锡", - "徐州", - "常州", - "苏州", - "南通", - "连云港", - "淮安", - "盐城", - "扬州", - "镇江", - "泰州", - "宿迁" - ] - ], - [ - "浙江", - [ - "杭州", - "宁波", - "温州", - "嘉兴", - "湖州", - "绍兴", - "金华", - "衢州", - "舟山", - "台州", - "丽水" - ] - ], - [ - "安徽", - [ - "合肥", - "芜湖", - "蚌埠", - "淮南", - "马鞍山", - "淮北", - "铜陵", - "安庆", - "黄山", - "滁州", - "阜阳", - "宿州", - "六安", - "亳州", - "池州", - "宣城" - ] - ], - [ - "福建", - [ - "福州", - "厦门", - "莆田", - "三明", - "泉州", - "漳州", - "南平", - "龙岩", - "宁德" - ] - ], - [ - "江西", - [ - "南昌", - "景德镇", - "萍乡", - "九江", - "新余", - "鹰潭", - "赣州", - "吉安", - "宜春", - "抚州", - "上饶" - ] - ], - [ - "山东", - [ - "济南", - "青岛", - "淄博", - "枣庄", - "东营", - "烟台", - "潍坊", - "济宁", - "泰安", - "威海", - "日照", - "临沂", - "德州", - "聊城", - "滨州", - "菏泽" - ] - ], - [ - "河南", - [ - "郑州", - "开封", - "洛阳", - "平顶山", - "安阳", - "鹤壁", - "新乡", - "焦作", - "濮阳", - "许昌", - "漯河", - "三门峡", - "南阳", - "商丘", - "信阳", - "周口", - "驻马店", - "济源" - ] - ], - [ - "湖北", - [ - "武汉", - "黄石", - "十堰", - "宜昌", - "襄阳", - "鄂州", - "荆门", - "孝感", - "荆州", - "黄冈", - "咸宁", - "随州", - "恩施", - "仙桃", - "潜江", - "天门", - "神农架" - ] - ], - [ - "湖南", - [ - "长沙", - "株洲", - "湘潭", - "衡阳", - "邵阳", - "岳阳", - "常德", - "张家界", - "益阳", - "郴州", - "永州", - "怀化", - "娄底", - "湘西" - ] - ], - [ - "广东", - [ - "广州", - "韶关", - "深圳", - "珠海", - "汕头", - "佛山", - "江门", - "湛江", - "茂名", - "肇庆", - "惠州", - "梅州", - "汕尾", - "河源", - "阳江", - "清远", - "潮州", - "揭阳", - "云浮" - ] - ], - [ - "广西", - [ - "南宁", - "柳州", - "桂林", - "梧州", - "北海", - "防城港", - "钦州", - "贵港", - "玉林", - "百色", - "贺州", - "河池", - "来宾", - "崇左" - ] - ], - [ - "海南", - [ - "海口", - "三亚", - "三沙", - "五指山", - "琼海", - "文昌", - "万宁", - "东方", - "定安", - "屯昌", - "澄迈", - "临高", - "白沙", - "昌江", - "乐东", - "陵水", - "保亭", - "琼中" - ] - ], - [ - "重庆", - [ - "重庆" - ] - ], - [ - "四川", - [ - "成都", - "自贡", - "攀枝花", - "泸州", - "德阳", - "绵阳", - "广元", - "遂宁", - "内江", - "乐山", - "南充", - "眉山", - "宜宾", - "广安", - "达州", - "雅安", - "巴中", - "资阳", - "阿坝", - "甘孜", - "凉山" - ] - ], - [ - "贵州", - [ - "贵阳", - "六盘水", - "遵义", - "安顺", - "毕节", - "铜仁", - "黔西南", - "黔东南", - "黔南" - ] - ], - [ - "云南", - [ - "昆明", - "曲靖", - "玉溪", - "保山", - "昭通", - "丽江", - "普洱", - "临沧", - "楚雄", - "红河", - "文山", - "西双版纳", - "大理", - "德宏", - "怒江", - "迪庆" - ] - ], - [ - "西藏", - [ - "拉萨", - "日喀则", - "昌都", - "林芝", - "山南", - "那曲", - "阿里" - ] - ], - [ - "陕西", - [ - "西安", - "铜川", - "宝鸡", - "咸阳", - "渭南", - "延安", - "汉中", - "榆林", - "安康", - "商洛" - ] - ], - [ - "甘肃", - [ - "兰州", - "嘉峪关", - "金昌", - "白银", - "天水", - "武威", - "张掖", - "平凉", - "酒泉", - "庆阳", - "定西", - "陇南", - "临夏", - "甘南" - ] - ], - [ - "青海", - [ - "西宁", - "海东", - "海北", - "黄南", - "海南", - "果洛", - "玉树", - "海西" - ] - ], - [ - "宁夏", - [ - "银川", - "石嘴山", - "吴忠", - "固原", - "中卫" - ] - ], - [ - "新疆", - [ - "乌鲁木齐", - "克拉玛依", - "吐鲁番", - "哈密", - "昌吉", - "博尔塔拉", - "巴音郭楞", - "阿克苏", - "克孜勒苏", - "喀什", - "和田", - "伊犁", - "塔城", - "阿勒泰", - "石河子", - "阿拉尔", - "图木舒克", - "五家渠", - "北屯", - "铁门关", - "双河", - "可克达拉", - "昆玉", - "胡杨河", - "新星" - ] - ] -]) -const adm2 = new Set([...adm.values()].flat()) - -export const adm1_def = "江苏" -export const adm2_def = "苏州" - -export function is_adm( - adm1adm2: [undefined | null | string, undefined | null | string] -): adm1adm2 is [string, string] { - const [adm1, adm2] = adm1adm2 - if (!adm1 || typeof adm1 !== "string") return false - if (!adm2 || typeof adm2 !== "string") return false - const a1 = adm.get(adm1) - if (!a1) return false - return a1.includes(adm2) -} -export function not_adm( - adm1adm2: [undefined | null | string, undefined | null | string] -) { - return !is_adm(adm1adm2) -} - -export function is_adm1( - a?: null | string -): a is string { - return typeof a === "string" && adm.has(a) -} -export function not_adm1( - a?: null | string -) { - return !is_adm1(a) -} - -export function is_adm2( - a?: null | string -): a is string { - return typeof a === "string" && adm2.has(a) -} -export function not_adm2( - a?: null | string -) { - return !is_adm2(a) -} diff --git a/ismism.ts/src/ont/base.ts b/ismism.ts/src/ont/base.ts deleted file mode 100644 index ee2ba40..0000000 --- a/ismism.ts/src/ont/base.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as base64 from "https://deno.land/std@0.173.0/encoding/base64url.ts" -import * as hex from "https://deno.land/std@0.173.0/encoding/hex.ts" - -const te = new TextEncoder() -const td = new TextDecoder() - -export function to_u8( - s: string -): Uint8Array { - return te.encode(s) -} -export function from_u8( - b: ArrayBuffer -): string { - return td.decode(b) -} - -export function to_base64( - b: ArrayBuffer -): string { - return base64.encode(b) -} -export function from_base64( - s: string -): Uint8Array { - return base64.decode(s) -} - -export function to_hex( - b: ArrayBuffer -): string { - return from_u8(hex.encode(new Uint8Array(b))) -} -export function from_hex( - s: string -): Uint8Array { - return hex.decode(to_u8(s)) -} - diff --git a/ismism.ts/src/ont/crypt.ts b/ismism.ts/src/ont/crypt.ts deleted file mode 100644 index ce95075..0000000 --- a/ismism.ts/src/ont/crypt.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { to_u8 } from "./base.ts" - -const alg = { - name: "HMAC", - hash: "SHA-256", -} - -export function key( - k: string | ArrayBuffer -): Promise { - if (typeof k === "string") k = to_u8(k) - return crypto.subtle.importKey("raw", k, alg, false, ["sign", "verify"]) -} - -export function sign( - key: CryptoKey, - data: string, -) { - return crypto.subtle.sign(alg.name, key, to_u8(data)) -} -export function verify( - key: CryptoKey, - data: string, - sig: Uint8Array, -) { - return crypto.subtle.verify(alg.name, key, sig, to_u8(data)) -} - -export async function digest( - data: string | ArrayBuffer, - niter = 1 -) { - if (typeof data === "string") data = to_u8(data) - for (let n = 0; n < niter; ++n) - data = await crypto.subtle.digest(alg.hash, data) - return data -} diff --git a/ismism.ts/src/ont/jwt.ts b/ismism.ts/src/ont/jwt.ts deleted file mode 100644 index 416e083..0000000 --- a/ismism.ts/src/ont/jwt.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { assert } from "https://deno.land/std@0.173.0/testing/asserts.ts" -import { from_base64, from_u8, to_base64, to_u8 } from "./base.ts" -import { key, sign, verify } from "./crypt.ts" - -type Json = Record - -const jwk_url = "./jwk.json" -let jwk: CryptoKey | null = null - -export async function jwk_set( - k: string -) { - jwk = await key(k) -} -export async function jwk_load( -) { - jwk_set(await Deno.readTextFile(jwk_url)) -} - -export async function jwt_sign( - json: Json -): Promise { - assert(jwk) - const p = to_base64(to_u8(JSON.stringify(json))) - const s = to_base64(await sign(jwk, p)) - return `${p}.${s}` -} -export async function jwt_verify( - jwt: string -): Promise { - const [p, s] = jwt.split(".") - if (!jwk || !s) return null - const v = await verify(jwk, p, from_base64(s)) - return v ? JSON.parse(from_u8(from_base64(p))) : null -} - diff --git a/ismism.ts/src/ont/sms.ts b/ismism.ts/src/ont/sms.ts deleted file mode 100644 index acee90e..0000000 --- a/ismism.ts/src/ont/sms.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { to_hex } from "./base.ts" -import { digest, key, sign } from "./crypt.ts" -import { utc_date } from "./utc.ts" - -const tc: { - id: string, - key: string, - service: string, - endpoint: string, - region: string, - ver: string, - appid: string, - sign: string, - template: string, -} = JSON.parse(await Deno.readTextFile("./tc.json")) - -type SendResponse = { - Response: { SendStatusSet: { Code: string }[] } -} - -export async function smssend( - nbr: string, - code: string, - hour: string, -) { - const body = JSON.stringify({ - PhoneNumberSet: [nbr], - SmsSdkAppId: tc.appid, - SignName: tc.sign, - TemplateId: tc.template, - TemplateParamSet: [code, hour], - }) - const alg = "TC3-HMAC-SHA256" - const t = Math.round(Date.now() / 1000) - const d = utc_date(t * 1000) - const scope = `${d}/${tc.service}/tc3_request` - const sigheader = "content-type;host" - const content_type = "application/json; charset=utf-8" - const req = `POST -/ - -content-type:${content_type} -host:${tc.endpoint} - -${sigheader} -${to_hex(await digest(body))}` - - const str = `${alg} -${t} -${scope} -${to_hex(await digest(req))}` - const kdate = await sign(await key(`TC3${tc.key}`), d) - const kservice = await sign(await key(kdate), tc.service) - const ksign = await sign(await key(kservice), "tc3_request") - const signature = to_hex(await sign(await key(ksign), str)) - const authorization = `${alg} Credential=${tc.id}/${scope}, SignedHeaders=${sigheader}, Signature=${signature}` - - const res = await fetch(`https://${tc.endpoint}`, { - method: "POST", - headers: { - "Authorization": authorization, - "Content-Type": content_type, - "Host": tc.endpoint, - "X-TC-Action": "SendSms", - "X-TC-Timestamp": `${t}`, - "X-TC-Version": tc.ver, - "X-TC-Region": tc.region, - }, - body, - }) - const json = await res.json() as SendResponse - return { - json, sent: json.Response.SendStatusSet[0]?.Code === "Ok" - } -} diff --git a/ismism.ts/src/ont/utc.ts b/ismism.ts/src/ont/utc.ts deleted file mode 100644 index 3b33e6e..0000000 --- a/ismism.ts/src/ont/utc.ts +++ /dev/null @@ -1,26 +0,0 @@ -export const utc_h = 60 * 60 * 1000 - -export function utc_short( - utc: number -) { - return new Date(utc).toLocaleString("zh-CN", { dateStyle: "short", timeStyle: "short" }).replaceAll("/", "-") -} -export function utc_medium( - utc: number -) { - return new Date(utc).toLocaleString("zh-CN", { dateStyle: "medium", timeStyle: "short" }) -} -export function utc_date( - utc: number -) { - const t = new Date(utc) - const y = t.getUTCFullYear() - const m = `${t.getUTCMonth() + 1}`.padStart(2, "0") - const d = `${t.getUTCDate()}`.padStart(2, "0") - return `${y}-${m}-${d}` -} - -export function utc_etag( -) { - return `W/"${Date.now()}"` -} diff --git a/ismism.ts/src/pra/con.ts b/ismism.ts/src/pra/con.ts deleted file mode 100644 index 833e375..0000000 --- a/ismism.ts/src/pra/con.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { Aut, Id } from "../eid/typ.ts" - -export function is_re( - re?: null | string -): re is "rej" | "ref" { - return re === "rej" || re === "ref" -} - -export function is_pro( - { rej, ref }: Pick, -): boolean { - return rej.length < 2 && ref.length >= 2 -} -export function not_pro( - re: Pick, -) { - return !is_pro(re) -} - -export function is_aut( - aut: Aut["aut"], - p: Aut["aut"][0], -): boolean { - return aut.includes(p) -} -export function not_aut( - aut: Aut["aut"], - p: Aut["aut"][0], -) { - return !is_aut(aut, p) -} - -export const goal_max = 9 diff --git a/ismism.ts/src/pra/doc.ts b/ismism.ts/src/pra/doc.ts deleted file mode 100644 index 5d49c51..0000000 --- a/ismism.ts/src/pra/doc.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { coll } from "../db.ts" -import { agd_r } from "../eid/agd.ts" -import { idnam } from "../eid/id.ts" -import { nrec } from "../eid/rec.ts" -import { soc_r } from "../eid/soc.ts" -import { Agd, Soc, Usr } from "../eid/typ.ts" -import { usr_r } from "../eid/usr.ts" -import { rolref } from "../eid/rel.ts" - -const pid = { nam: 1, rej: 1, ref: 1, utc: 1, adm1: 1, adm2: 1, intro: 1 } as const -const psoc = { sec: 1, reslim: 1, res: 1, uidlim: 1, uid: 1 } as const - -export async function usr( - _id: Usr["_id"], -) { - const [u, sref, aref, nr] = await Promise.all([ - usr_r({ _id }, pid), - rolref(coll.soc, _id), rolref(coll.agd, _id), - nrec({ uid: [_id] }) - ]) - if (!u || !sref || !aref || !nr) return null - const [unam, snam, anam] = await Promise.all([ - idnam(coll.usr, [...u.rej, ...u.ref]), - idnam(coll.soc, Object.values(sref).flatMap(s => s.map(p => p[0]))), - idnam(coll.agd, Object.values(aref).flatMap(s => s.map(p => p[0]))), - ]) - return { - ...u, sref, aref, unam, snam, anam, nrec: nr - } -} - -export async function soc( - _id: Soc["_id"] -) { - const s = await soc_r(_id, { ...pid, ...psoc }) - if (!s) return null - const [unam, nr] = await Promise.all([ - idnam(coll.usr, [...s.rej, ...s.ref, ...s.sec, ...s.res, ...s.uid]), - nrec({ uid: s.uid }), - ]) - return { ...s, unam, nrec: nr } -} - -export async function agd( - _id: Agd["_id"] -) { - const a = await agd_r(_id, { ...pid, ...psoc, detail: 1, budget: 1, fund: 1, expense: 1, goal: 1, img: 1 }) - if (!a) return null - const [unam, nr] = await Promise.all([ - idnam(coll.usr, [...a.rej, ...a.ref, ...a.sec, ...a.res, ...a.uid]), - nrec({ aid: _id }), - ]) - return { ...a, unam, nrec: nr } -} diff --git a/ismism.ts/src/pra/pas.ts b/ismism.ts/src/pra/pas.ts deleted file mode 100644 index 8af40c5..0000000 --- a/ismism.ts/src/pra/pas.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Aut, Usr } from "../eid/typ.ts" -import { coll, DocR, DocU } from "../db.ts" -import { jwt_sign, jwt_verify } from "../ont/jwt.ts" -import { usr_r, usr_u } from "../eid/usr.ts" -import { aut_r } from "../eid/aut.ts" -import { utc_h } from "../ont/utc.ts" -import { smssend } from "../ont/sms.ts" -import { rol, Rol } from "../eid/rel.ts" - -export type Pas = { - id: { uid: Usr["_id"], utc: number }, - rej: Usr["rej"], - ref: Usr["ref"], - nam: Usr["nam"], - aut: Aut["aut"], - sid: Rol, - aid: Rol, -} - -async function pas_of_usr( - u: Pick -): DocR { - const [aut, sid, aid] = await Promise.all([ - aut_r(u._id), rol(coll.soc, u._id), rol(coll.agd, u._id), - ]) - if (!sid || !aid) return null - return { - id: { uid: u._id, utc: Date.now() }, - rej: u.rej, ref: u.ref, - nam: u.nam, - aut: aut ? aut.aut : [], - sid, aid, - } -} - -const utc_pas_valid = new Date("2023-01-29").getTime() -const h_pcode_valid = 1 -export const pcode_digit = 6 - -export async function pas( - jwt: NonNullable -): DocR { - const id = await jwt_verify(jwt) - if (!id) return null - const u = await usr_r({ _id: id.uid }, { rej: 1, ref: 1, nam: 1, pcode: 1, ptoken: 1 }) - if (u && u.pcode && u.pcode.utc > utc_pas_valid && u.ptoken && u.ptoken === jwt) - return pas_of_usr(u) - return null -} - -export async function pas_issue( - nbr: NonNullable, - code: NonNullable["code"], -): DocR<{ pas: Pas, jwt: NonNullable }> { - const u = await usr_r({ nbr }, { rej: 1, ref: 1, nam: 1, pcode: 1, ptoken: 1 }) - const utc = Date.now() - if (u && u.pcode && u.pcode.code === code && utc - u.pcode.utc < utc_h * h_pcode_valid) { - const pas = await pas_of_usr(u) - if (!pas) return null - if (u.ptoken) return { pas, jwt: u.ptoken } - const jwt = await jwt_sign(pas.id) - const c = await usr_u(u._id, { $set: { ptoken: jwt } }) - if (c && c > 0) return { pas, jwt } - } - return null -} - -export async function pas_code( - nbr: NonNullable, - sms: boolean, -): DocR<{ sms: boolean, utc?: number }> { - const u = await usr_r({ nbr }, { nam: 1, pcode: 1, ptoken: 1 }) - if (!u) return null - const utc = Date.now() - if (u.pcode && utc - u.pcode.utc < utc_h * h_pcode_valid) - return { sms: false, utc: u.pcode.utc } - const code = Math.round(Math.random() * 1000000) - const c = await usr_u(u._id, { $set: { pcode: { code, utc } } }) - if (c && c > 0) { - if (sms) { - const { sent } = await smssend(nbr, `${code}`.padStart(pcode_digit, "0"), `${h_pcode_valid}`) - return { sms: sent } - } - return { sms: false } - } - return null -} - -export function pas_clear( - uid: Usr["_id"] -): DocU { - return usr_u(uid, { $unset: { ptoken: "" } }) -} diff --git a/ismism.ts/src/pra/pos.ts b/ismism.ts/src/pra/pos.ts deleted file mode 100644 index 223cd1d..0000000 --- a/ismism.ts/src/pra/pos.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { utc_etag } from "../ont/utc.ts" -import { is_re } from "./con.ts" -import { pas, Pas, pas_clear, pas_code, pas_issue } from "./pas.ts" -import { pre_agd, pre_soc, pre_usr, pre_usract } from "./pre.ts" -import { pro_agd, pro_rec, pro_soc, pro_usr } from "./pro.ts" -import { put_agd, put_agd_goal, put_soc, put_soc_res, put_soc_sec, put_soc_uid, put_usr } from "./put.ts" - -// deno-lint-ignore no-explicit-any -type Ret any> = Awaited> - -export type Pos = "pas" | "pre" | "pro" -export type PasPos = { jwt?: string | null, pas?: Pas | null, etag?: string | null } -export type PasCode = Ret -export type UsrAct = Ret - -export async function pos( - p: PasPos, - f: Pos | string, - b: string, -) { - let json - try { json = b.length > 0 ? JSON.parse(b) : {} } - catch { return null } - - if (p.jwt) { - p.pas = await pas(p.jwt) - p.jwt = null - } else p.pas = null - - switch (f) { - case "pas": { - const { uid, sms, nbr, code } = json - if (typeof uid === "number") { - p.jwt = null - if (p.pas && uid === p.pas.id.uid) { - p.pas = null - return pas_clear(uid) - } - } else if (typeof sms === "boolean" && typeof nbr === "string") { - return await pas_code(nbr, sms) - } else if (typeof nbr === "string" && typeof code === "number") { - const issue = await pas_issue(nbr, code) - if (issue) { - p.pas = issue.pas - p.jwt = issue.jwt - return issue.pas - } - } else if (p.pas) return p.pas - break - } - - case "pre": { - p.etag = utc_etag() - const { actid, nbr, snam, anam, adm1, adm2 } = json - if (typeof adm1 === "string" && typeof adm2 === "string") - if (typeof nbr === "string") { - if (typeof actid === "string") return pre_usract(actid, nbr, adm1, adm2) - else if (p.pas) return pre_usr(p.pas, nbr, adm1, adm2) - } else if (p.pas) { - if (typeof snam === "string") return pre_soc(p.pas, snam, adm1, adm2) - else if (typeof anam === "string") return pre_agd(p.pas, anam, adm1, adm2) - } - break - } - - case "pro": { - p.etag = utc_etag() - const { re, uid, sid, aid, rec, recid, pro } = json - if (p.pas && is_re(re) && typeof pro === "boolean") - if (typeof uid === "number") return pro_usr(p.pas, re, uid, pro) - else if (typeof sid === "number") return pro_soc(p.pas, re, sid, pro) - else if (typeof aid === "number") return pro_agd(p.pas, re, aid, pro) - else if (typeof rec === "string" && typeof recid === "object") return pro_rec(p.pas, re, rec, recid, pro) - break - } - - case "put": { - p.etag = utc_etag() - const { uid, sid, aid, nam, adm1, adm2, intro, reslim, detail, sec, res, goal, pct, pro } = json - if (p.pas && typeof nam === "string" && typeof adm1 === "string" && typeof adm2 === "string" && typeof intro === "string") { - if (typeof uid === "number") return put_usr(p.pas, uid, { nam, adm1, adm2, intro }) - else if (typeof sid === "number" && typeof reslim === "number") - return put_soc(p.pas, sid, { nam, adm1, adm2, intro, reslim }) - else if (typeof aid === "number" && typeof reslim === "number" && typeof detail === "string") - return put_agd(p.pas, aid, { nam, adm1, adm2, intro, reslim, detail }) - } else if (p.pas && typeof sid === "number") { - if (typeof sec === "boolean" && typeof uid === "number") return put_soc_sec(p.pas, sid, uid, sec) - else if (typeof res === "boolean") return put_soc_res(p.pas, sid, res) - else if (typeof pro === "boolean" && typeof uid === "number") return put_soc_uid(p.pas, sid, uid, pro) - } else if (p.pas && typeof aid === "number" && typeof goal === "string" && (pct === undefined || typeof pct === "number")) { - return put_agd_goal(p.pas, aid, goal, pct) - } - break - } - } - - p.etag = null - return null -} diff --git a/ismism.ts/src/pra/pre.ts b/ismism.ts/src/pra/pre.ts deleted file mode 100644 index a482f92..0000000 --- a/ismism.ts/src/pra/pre.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Act, Soc, Usr, Agd } from "../eid/typ.ts" -import { act_u, act_r } from "../eid/act.ts" -import { usr_c, usr_u } from "../eid/usr.ts" -import { DocC } from "../db.ts" -import { Pas } from "./pas.ts" -import { soc_c } from "../eid/soc.ts" -import { agd_c } from "../eid/agd.ts" -import { is_id } from "../eid/is.ts"; -import { not_aut, not_pro } from "./con.ts" - -export async function pre_usract( - actid: Act["_id"], - nbr: NonNullable, - adm1: string, - adm2: string, -): DocC { - const a = await act_r(actid) - if (a) switch (a.act) { - case "usrfund": { - const uid = await usr_c(nbr, a.ref, adm1, adm2) - if (is_id(uid)) await act_u(actid, { $set: { exp: Date.now() } }) - return uid - } case "usrnbr": { - const u = await usr_u(a.uid, { $set: { nbr, adm1, adm2 } }) - if (u && u > 0) { - await act_u(actid, { $set: { exp: Date.now() } }) - return a.uid - } break - } - } - return null -} - -export async function pre_usr( - pas: Pas, - nbr: NonNullable, - adm1: string, - adm2: string, -): DocC { - if (not_aut(pas.aut, "pre_usr") || not_pro(pas)) return null - return await usr_c(nbr, [pas.id.uid], adm1, adm2) -} -export async function pre_soc( - pas: Pas, - nam: Soc["nam"], - adm1: string, - adm2: string, -): DocC { - if (not_aut(pas.aut, "pre_soc") || not_pro(pas)) return null - return await soc_c(nam, pas.id.uid, adm1, adm2) -} -export async function pre_agd( - pas: Pas, - nam: Agd["nam"], - adm1: string, - adm2: string, -): DocC { - if (not_aut(pas.aut, "pre_agd") || not_pro(pas)) return null - return await agd_c(nam, pas.id.uid, adm1, adm2) -} diff --git a/ismism.ts/src/pra/pro.ts b/ismism.ts/src/pra/pro.ts deleted file mode 100644 index f56d4a6..0000000 --- a/ismism.ts/src/pra/pro.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { DocU } from "../db.ts" -import { agd_u } from "../eid/agd.ts" -import { Agd, Rec, Soc, Usr } from "../eid/typ.ts" -import { collrec, rec_u } from "../eid/rec.ts" -import { not_recid } from "../eid/is.ts" -import { soc_u } from "../eid/soc.ts" -import { usr_u } from "../eid/usr.ts" -import { Pas } from "./pas.ts" -import { not_aut, not_pro } from "./con.ts" - -export async function pro_usr( - pas: Pas, - re: "rej" | "ref", - uid: Usr["_id"], - pro: boolean, -): DocU { - if (not_aut(pas.aut, "pre_usr") || not_pro(pas) || pas.ref.includes(uid)) return null - const u = { [re]: pas.id.uid } - return await usr_u(uid, pro ? { $addToSet: u } : { $pull: u }) -} -export async function pro_soc( - pas: Pas, - re: "rej" | "ref", - sid: Soc["_id"], - pro: boolean, -): DocU { - if (not_aut(pas.aut, "pre_soc") || not_pro(pas)) return null - const u = { [re]: pas.id.uid } - return await soc_u(sid, pro ? { $addToSet: u } : { $pull: u }) -} -export async function pro_agd( - pas: Pas, - re: "rej" | "ref", - aid: Agd["_id"], - pro: boolean, -): DocU { - if (not_aut(pas.aut, "pre_agd") || not_pro(pas)) return null - const u = { [re]: pas.id.uid } - return await agd_u(aid, pro ? { $addToSet: u } : { $pull: u }) -} - -export async function pro_rec( - pas: Pas, - re: "rej" | "ref", - rec: "work" | "fund" | string, - recid: Rec["_id"], - pro: boolean, -): DocU { - if (not_recid(recid) || not_pro(pas)) return null - const c = collrec(rec) - const not_sec = !pas.aid.sec.includes(recid.aid) - const not_uid = !pas.aid.uid.includes(recid.aid) - if (!c || not_sec && re === "ref" || not_sec && not_uid) return null - const u = { [re]: pas.id.uid } - return await rec_u(c, recid, pro ? { $addToSet: u } : { $pull: u }) -} diff --git a/ismism.ts/src/pra/put.ts b/ismism.ts/src/pra/put.ts deleted file mode 100644 index 673c54d..0000000 --- a/ismism.ts/src/pra/put.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { DocU } from "../db.ts" -import { agd_r, agd_u } from "../eid/agd.ts" -import { not_id } from "../eid/is.ts" -import { soc_r, soc_u } from "../eid/soc.ts" -import { Agd, Soc, Usr } from "../eid/typ.ts" -import { usr_r, usr_u } from "../eid/usr.ts" -import { goal_max, not_aut, not_pro } from "./con.ts" -import { Pas } from "./pas.ts" - -export async function put_usr( - pas: Pas, - uid: Usr["_id"], - u: Pick -): DocU { - if (pas.id.uid !== uid) return null - return await usr_u(uid, { $set: u }) -} - -export async function put_soc( - pas: Pas, - sid: Soc["_id"], - s: Pick, -): DocU { - if (not_pro(pas)) return null - const na = not_aut(pas.aut, "pre_soc") - const sec = await soc_r(sid, { sec: 1 }) - if (!sec || na && !sec.sec.includes(pas.id.uid)) return null - return await soc_u(sid, { $set: na ? { intro: s.intro, reslim: s.reslim, } : s }) -} - -export async function put_agd( - pas: Pas, - aid: Agd["_id"], - a: Pick, -): DocU { - const na = not_aut(pas.aut, "pre_agd") - if (na && !pas.aid.sec.includes(aid) || not_pro(pas)) return null - return await agd_u(aid, { $set: na ? { intro: a.intro, reslim: a.reslim, detail: a.detail } : a }) -} - -export async function put_soc_sec( - pas: Pas, - sid: Soc["_id"], - uid: Usr["_id"], - sec: boolean, -): DocU { - if (not_id(uid) || not_aut(pas.aut, "pre_soc") || not_pro(pas)) return null - return await soc_u(sid, sec ? { $addToSet: { sec: uid } } : { $pull: { sec: uid } }) -} - -export async function put_soc_res( - pas: Pas, - sid: Soc["_id"], - res: boolean, -): DocU { - if (not_pro(pas)) return null - const s = await soc_r(sid, { uid: 1 }) - if (!s || s.uid.includes(pas.id.uid)) return null - return await soc_u(sid, res ? { $addToSet: { res: pas.id.uid } } : { $pull: { res: pas.id.uid } }) -} - -export async function put_soc_uid( - pas: Pas, - sid: Soc["_id"], - uid: Usr["_id"], - pro: boolean, -): DocU { - if (not_pro(pas)) return null - const [s, u] = await Promise.all([ - soc_r(sid, { sec: 1, uid: 1, res: 1 }), - usr_r({ _id: uid }, { rej: 1, ref: 1 }), - ]) - if (!s || !u) return null - if (pro && s.res.includes(uid) - && u.rej.length < 2 - && u.ref.filter(r => s.sec.includes(r)).length >= 2 - && s.sec.includes(pas.id.uid) - ) return await soc_u(sid, { $addToSet: { uid }, $pull: { res: uid } }) - if (!pro && (s.uid.includes(uid) && uid === pas.id.uid - || s.res.includes(uid) && s.sec.includes(pas.id.uid) - )) return await soc_u(sid, { $pull: { uid, res: uid } }) - return null -} - -export async function put_agd_goal( - pas: Pas, - aid: Agd["_id"], - goal: Agd["goal"][0]["nam"], - pct?: Agd["goal"][0]["pct"], -): DocU { - if (!pas.aid.sec.includes(aid) || not_pro(pas)) return null - const a = await agd_r(aid, { goal: 1 }) - if (!a) return null - if (pct === undefined) a.goal = a.goal.filter(g => g.nam !== goal).slice(0, goal_max) - else { - const n = a.goal.findIndex(g => g.nam === goal) - if (n >= 0) a.goal[n].pct = pct - else if (a.goal.length >= goal_max) return null - else a.goal.push({ nam: goal, pct }) - } - return await agd_u(aid, { $set: { goal: a.goal.sort((a, b) => a.pct - b.pct) } }) -} diff --git a/ismism.ts/src/pra/que.ts b/ismism.ts/src/pra/que.ts deleted file mode 100644 index 4d86287..0000000 --- a/ismism.ts/src/pra/que.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Coll, coll } from "../db.ts" -import { id_of_adm } from "../eid/id.ts" -import { agd, soc, usr } from "./doc.ts" - -// deno-lint-ignore no-explicit-any -type Ret any> = Awaited> - -export type Usr = Ret -export type Soc = Ret -export type Agd = Ret - -function id( - c: Coll["soc" | "agd"], - p: URLSearchParams, -) { - const [adm1, adm2] = [p.get("adm1"), p.get("adm2")] - return id_of_adm(c, adm2 ? { adm2 } : adm1 ? { adm1 } : undefined) -} - -export async function que( - f: string, - p: URLSearchParams, -) { - switch (f) { - case "usr": { - const uid = parseInt(p.get("uid") ?? "") - return await usr(uid) - } case "soc": { - if (p.has("sid")) { - const sid = parseInt(p.get("sid") ?? "") - return await soc(sid) - } - const sid = await id(coll.soc, p) - return await Promise.all(sid.map(soc)) - } case "agd": { - if (p.has("aid")) { - const aid = parseInt(p.get("aid") ?? "") - return await agd(aid) - } - const aid = await id(coll.agd, p) - return await Promise.all(aid.map(agd)) - } case "rec": { - break - } - } - return null -} diff --git a/ismism.ts/src/ser.ts b/ismism.ts/src/ser.ts deleted file mode 100644 index a1deb3f..0000000 --- a/ismism.ts/src/ser.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { serve } from "https://deno.land/std@0.173.0/http/server.ts" -import { jwk_load } from "./ont/jwt.ts" -import { utc_etag, utc_short } from "./ont/utc.ts" -import { pos, PasPos } from "./pra/pos.ts" -import { que } from "./pra/que.ts" - -let etag = utc_etag() - -function log( - utc: number, - msg: string, - status?: number, -) { - console.log(`${utc_short(utc)} - ${msg} - ${status ?? ""} - ${etag}`) -} - -async function route( - req: Request -): Promise { - const url = new URL(req.url) - const [_, r, f] = url.pathname.split("/") - const t = Date.now() - switch (r) { - case "quit": { - log(t, "quit") - Deno.exit(); break - } case "update": { - etag = `W/"${t}"` - log(t, "etag updated") - return new Response(null, { status: 200, headers: { etag } }) - } case "q": { - if (req.headers.get("if-none-match")?.includes(etag)) { - log(t, `${f}${url.search}`, 304) - return new Response(null, { status: 304, headers: { etag } }) - } - log(t, `${f}${url.search}`, 200) - return new Response( - JSON.stringify(await que(f, url.searchParams)), { - status: 200, - headers: { etag } - }) - } case "p": { - const p: PasPos = {} - const [cookie] = req.headers.get("cookie")?.split(";").filter(c => c.startsWith("pp=")) ?? [] - if (cookie) p.jwt = cookie.substring(3) - const b = await req.text() - const r = await pos(p, f, b) - if (r && p.etag) etag = p.etag - const s = JSON.stringify(r) - log(t, `${f}#${p.pas?.id.uid ?? ""} ${b} => ${s}`, 200) - const headers: Headers = new Headers() - if (!p.pas) headers.set("set-cookie", `pp=""; Path=/p; SameSite=Strict; Secure; HttpOnly; Max-Age=0`) - else if (p.jwt) headers.set("set-cookie", `pp=${p.jwt}; Path=/p; SameSite=Strict; Secure; HttpOnly; Max-Age=31728728`) - return new Response(s, { status: 200, headers }) - } - } - return new Response(null, { status: 400 }) -} - -await jwk_load() -serve(route, { port: 728 }) diff --git a/ismism.ts/tst/eid.test.ts b/ismism.ts/tst/eid.test.ts deleted file mode 100644 index 701d5c8..0000000 --- a/ismism.ts/tst/eid.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { assert, assertEquals } from "https://deno.land/std@0.173.0/testing/asserts.ts" -import { coll, db } from "../src/db.ts" -import { act_c, act_d, act_r, act_u } from "../src/eid/act.ts" -import { agd_c, agd_d, agd_r, agd_u } from "../src/eid/agd.ts" -import { aut_c, aut_d, aut_r, aut_u } from "../src/eid/aut.ts" -import { id, idnam, nid_of_adm } from "../src/eid/id.ts" -import { is_id, is_intro, is_nam, not_id, not_intro, not_nam, is_rol, not_rol, is_nbr, not_nbr } from "../src/eid/is.ts" -import { nrec, rec_c, rec_d, rec_r, rec_u, rol } from "../src/eid/rec.ts" -import { soc_c, soc_d, sidnam, soc_r, soc_u } from "../src/eid/soc.ts" -import { usr_c, usr_r, usr_u, usr_d } from "../src/eid/usr.ts" - -await db("tst", true) - -Deno.test("id", async () => { - assert(is_id(1) && is_id(9999)) - assert(not_id(undefined) && not_id(null) && not_id(0) && not_id(-2)) - - assert(is_nam("中文")) - assert(not_nam(undefined) && not_nam(null)) - assert(not_nam("abcd") && not_nam("123") && not_nam("中") && not_nam("文".repeat(17))) - - assert(is_intro("") && is_intro("123abc") && is_intro("中文") && "文".repeat(4096)) - assert(not_intro(undefined) && not_intro(null) && not_intro("a".repeat(4097))) - - assert((await idnam(coll.soc, [])).length === 0) - assert((await idnam(coll.soc, [1, 2, 3])).length === 0) - assert((await id(coll.soc)).length === 0) - assert((await id(coll.soc, { adm1: "成都" })).length === 0) - assert((await nid_of_adm(coll.soc, "adm1")).length === 0) - - const sidnam = ["社团一", "社团二", "社团三"] - const sid = [ - await soc_c(sidnam[0], [], "四川", "成都", ""), - await soc_c(sidnam[1], [], "四川", "成都", ""), - await soc_c(sidnam[2], [], "广东", "汕头", ""), - ].filter(is_id) - assert(sid.length == 3) - - assertEquals(await idnam(coll.soc, sid), sid.map((u, n) => [u, sidnam[n]])) - assertEquals(await id(coll.soc), sid.reverse()) - assertEquals(await id(coll.soc, { adm1: "广东" }), [3]) - assertEquals(await id(coll.soc, { adm2: "成都" }), [2, 1]) - assertEquals(await nid_of_adm(coll.soc, "adm1"), [["四川", 2], ["广东", 1]]) - assertEquals(await nid_of_adm(coll.soc, "adm2"), [["成都", 2], ["汕头", 1]]) - - await Promise.all(sid.map(soc_d)) -}) - -Deno.test("nbr", () => { - assert(is_nbr("11111111111")) - assert(not_nbr(undefined) && not_nbr(null) && not_nbr("") && not_nbr("123")) -}) - -Deno.test("usr", async () => { - const nbr = "11111111114" - assert(null === await usr_r({ _id: 1 }, { nbr: 1 })) - const r_c = await usr_c(nbr, [], "四川", "成都") - assert(r_c && r_c === 1) - const u = await usr_r({ _id: r_c }, { nam: 1, intro: 1, adm2: 1, nbr: 1 }) - assert(u && u.nam === "1" && u.intro.length === 0 && u.adm2 === "成都" && u.nbr === nbr) - await usr_u(r_c, { $set: { nam: "中文名", adm1: "广东", adm2: "汕头", intro: "介绍" } }) - const u2 = await usr_r({ _id: r_c }, { nam: 1, adm2: 1, intro: 1 }) - assert(u2 && u2.nam === "中文名" && u2.adm2 === "汕头" && u2.intro.length === 2) - await usr_u(r_c, { $addToSet: { ref: { $each: [1, 2, 3] } } }) - assertEquals(await usr_u(r_c, { $addToSet: { ref: 2 } }), 0) - assertEquals(await usr_r({ _id: r_c }, { ref: 1 }), { _id: r_c, ref: [1, 2, 3] }) - await usr_u(r_c, { $pull: { ref: 2 } }) - assertEquals(await usr_r({ _id: r_c }, { ref: 1 }), { _id: r_c, ref: [1, 3] }) - await usr_d(r_c) - assert(null === await usr_r({ _id: 1 }, { nbr: 1 })) -}) - -Deno.test("soc", async () => { - const nam = "社团" - assert(null === await soc_r(1, {})) - const r_c = await soc_c(nam, [1], "四川", "成都", nam) - assert(r_c && r_c === 1) - const s = await soc_r(r_c, { nam: 1, intro: 1, adm1: 1, uid: 1 }) - assert(s && s.nam === nam && s.intro === nam && s.adm1 === "四川" && s.uid.length === 0) - await soc_u(r_c, { $set: { sec: [2], ref: [2], uid: [2, 3, 4] } }) - const s2 = await soc_r(r_c, { sec: 1, ref: 1, uid: 1 }) - assertEquals(s2, { _id: 1, sec: [2], ref: [2], uid: [2, 3, 4] }) - assertEquals([[1, "社团"]], await sidnam(3)) - await soc_d(r_c) - assert(null === await soc_r(r_c, {})) -}) - -Deno.test("agd", async () => { - const nam = "活动" - assert(null === await agd_r(1, {})) - const r_c = await agd_c(nam, [1], "四川", "成都", nam) - assert(r_c && r_c === 1) - const s = await agd_r(r_c, { nam: 1, intro: 1, adm1: 1, goal: 1 }) - assert(s && s.nam === nam && s.intro === nam && s.adm1 === "四川" && s.goal.length === 0) - await agd_u(r_c, { $set: { ref: [2], goal: [{ nam: "目标", pct: 75 }], img: [{ nam: "a", src: "b" }] } }) - const s2 = await agd_r(r_c, { ref: 1, goal: 1, img: 1 }) - assertEquals(s2, { _id: 1, ref: [2], goal: [{ nam: "目标", pct: 75 }], img: [{ nam: "a", src: "b" }] }) - await agd_d(r_c) - assert(null === await agd_r(r_c, {})) -}) - -Deno.test("rec", async () => { - const utc = Date.now() - const id = [ - { uid: 1, aid: 4, utc }, - { uid: 2, aid: 4, utc: utc + 100 }, - { uid: 2, aid: 3, utc: utc + 200 }, - ] - - assertEquals(await nrec(), { worker: 0, work: 0, fund: 0 }) - assertEquals(await nrec({ aid: 4 }), { worker: 0, work: 0, fund: 0 }) - assert(0 === (await rec_r(coll.worker, 0))?.length) - assert(0 === (await rec_r(coll.work, utc))?.length) - assert(0 === (await rec_r(coll.fund, utc, { "_id.uid": 2 }))?.length) - - assertEquals(id, await Promise.all(id.map(_id => rec_c(coll.worker, { - _id, ref: [_id.uid, 3], rej: [], rol: "sec", exp: utc + 10000 - })))) - assertEquals(id, await Promise.all(id.map(_id => rec_c(coll.work, { - _id, ref: [_id.uid], rej: [], work: "work", msg: "msg" - })))) - assertEquals(id, await Promise.all(id.map(_id => rec_c(coll.fund, { - _id, ref: [_id.uid], rej: [], fund: 32, msg: "msg" - })))) - assertEquals(await nrec(), { worker: 3, work: 3, fund: 3 }) - assertEquals(await nrec({ uid: [2] }), { worker: 2, work: 2, fund: 2 }) - assertEquals(await nrec({ aid: 4 }), { worker: 2, work: 2, fund: 2 }) - - const r = await rol([2, 3, 4, 1]) - r.sort((a, b) => a[0] - b[0]) - assertEquals(r, [[1, [[4, "sec"]]], [2, [[3, "sec"], [4, "sec"]]]]) - assert(is_rol(r[0][1], [4, "sec"])) - assert(is_rol(r[1][1], [3, "sec"])) - assert(not_rol(r[1][1], [3, "worker"])) - - assertEquals((await rec_r(coll.worker, 0))!.length, 3) - assertEquals((await rec_r(coll.work, utc + 100))!.length, 1) - assertEquals((await rec_r(coll.fund, utc))!.map(r => r._id), id.slice(1).reverse()) - assertEquals((await rec_r(coll.worker, utc - 100, { "_id.aid": 4 }))!.map(r => r._id), id.slice(0, 2).reverse()) - assertEquals((await rec_r(coll.work, utc, { "_id.uid": 2 }))!.map(r => r._id), id.slice(1).reverse()) - assertEquals((await rec_r(coll.work, 0, { "_id.aid": 4 }, { work: "video" })), []) - - assertEquals(await rec_u(coll.work, id[1], { $set: { msg: "updated" } }), 1) - assertEquals((await rec_r(coll.work, utc, { "_id.aid": 4 }, { work: "work" }))! - .map(w => w.work == "work" ? w.msg : ""), - ["updated"] - ); - - await Promise.all([ - coll.worker, coll.work, coll.fund - ].flatMap(c => id.map(_id => rec_d(c, _id)))) - assertEquals(await nrec(), { worker: 0, work: 0, fund: 0 }) -}) - -Deno.test("act", async () => { - const _id = "111111" - assert(null === await act_r(_id)) - await act_c({ _id, exp: Date.now() + 100000, act: "usrnew", ref: [] }) - assertEquals((await act_r(_id))?.act, "usrnew") - await act_u(_id, { $set: { exp: Date.now() } }) - assert(null === await act_r(_id)) - assert(1 === await act_d(_id)) -}) - -Deno.test("aut", async () => { - const _id = 1 - assert(null === await aut_r(_id)) - await aut_c({ _id, aut: ["pre_usr", "pre_soc"] }) - assertEquals((await aut_r(_id))?.aut, ["pre_usr", "pre_soc"]) - await aut_u(_id, { $addToSet: { aut: { $each: ["pre_soc", "pre_agd"] } } }) - await aut_u(_id, { $pull: { aut: "pre_usr" } }) - assertEquals((await aut_r(_id))?.aut, ["pre_soc", "pre_agd"]) - assert(1 === await aut_d(_id)) -}) diff --git a/ismism.ts/tst/ont.test.ts b/ismism.ts/tst/ont.test.ts deleted file mode 100644 index f9da0d6..0000000 --- a/ismism.ts/tst/ont.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { assert, assertEquals, assertRejects } from "https://deno.land/std@0.173.0/testing/asserts.ts" -import { is_adm, is_adm1, is_adm2, not_adm, not_adm1, not_adm2 } from "../src/ont/adm.ts" -import { from_base64, from_hex, from_u8, to_base64, to_hex, to_u8 } from "../src/ont/base.ts" -import { digest } from "../src/ont/crypt.ts" -import { jwk_load, jwk_set, jwt_sign, jwt_verify } from "../src/ont/jwt.ts" -import { utc_date, utc_h, utc_medium, utc_short } from "../src/ont/utc.ts" - -Deno.test("base", () => { - const t = "this is a test 1234" - assert(t == from_u8(to_u8(t))) - - const bl = 1023 - const b = new Uint8Array(bl) - b.forEach((_, n) => b[n] = Math.floor(Math.random() * 256)) - assertEquals(b.length, bl) - - assertEquals(b, from_base64(to_base64(b))) - assertEquals(bl / 3 * 4, to_base64(b).length) - - assertEquals(b, from_hex(to_hex(b))) - assertEquals(bl * 2, to_hex(b).length) -}) - -Deno.test("utc", () => { - const t = Date.now() - const [m, s, d] = [utc_medium(t), utc_short(t), utc_date(t)] - assert(m.length > s.length && s.length > d.length && d.length > 0) -}) - -Deno.test("adm", () => { - assert(is_adm(["四川", "成都"]) && is_adm(["广东", "汕头"])) - assert(not_adm([undefined, null]) && not_adm(["广东", "成都"]) && not_adm(["", ""])) - - assert(is_adm1("四川") && is_adm1("广东")) - assert(not_adm1(undefined) && not_adm1(null) && not_adm2("") && not_adm1("成都")) - - assert(is_adm2("成都") && is_adm2("汕头")) - assert(not_adm2(undefined) && not_adm2(null) && not_adm2("") && not_adm2("四川")) -}) - -Deno.test("dig", async () => { - const h = `${Math.floor(Date.now() % utc_h * Math.random())}` - const h1000 = await digest(h, 1000) - const h999 = await digest(h, 999) - const h999_1 = await digest(h999) - assertEquals(h1000, h999_1) -}) - -Deno.test("jwt", async () => { - const json = { uid: 1000, nam: "nam", utc: Date.now() } - assertRejects(() => jwt_sign(json)) - await jwk_load() - assert(null == await jwt_verify("")) - const token = await jwt_sign(json) - assert(token.length > 0 && token.split(".").length == 2) - assert(null == await jwt_verify(token.substring(1))) - assertEquals(await jwt_verify(token), json) - await jwk_set("anotherkey") - assert(null == await jwt_verify(token)) - const token2 = await jwt_sign(json) - assert(token != token2) - assertEquals(await jwt_verify(token2), json) -}) diff --git a/ismism.ts/tst/pos.test.ts b/ismism.ts/tst/pos.test.ts deleted file mode 100644 index 10cf2ac..0000000 --- a/ismism.ts/tst/pos.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { assert, assertEquals } from "https://deno.land/std@0.173.0/testing/asserts.ts" -import { coll, db } from "../src/db.ts" -import { act_c, act_d } from "../src/eid/act.ts" -import { agd_c, agd_d } from "../src/eid/agd.ts" -import { aut_c, aut_d } from "../src/eid/aut.ts" -import { rec_c, rec_d } from "../src/eid/rec.ts" -import { soc_c, soc_d, soc_r, soc_u } from "../src/eid/soc.ts" -import { usr_c, usr_d, usr_r } from "../src/eid/usr.ts" -import { jwk_set } from "../src/ont/jwt.ts" -import { Pas } from "../src/pra/pas.ts" -import { PasCode, pos } from "../src/pra/pos.ts" -import { PasPos } from "../src/pra/pos.ts" - -await db("tst", true) -await jwk_set("testkey") - -const json = JSON.stringify - -Deno.test("pas", async () => { - const nbr = "11111111111" - const uid = await usr_c(nbr, [1, 2], "四川", "成都") - assert(uid === 1) - const p: PasPos = {} - assert(null === await pos(p, "pas", "")) - assertEquals(p, { etag: null, pas: null }) - assertEquals(await pos(p, "pas", json({ nbr, sms: false })), { sms: false }) - const pascode = await pos(p, "pas", json({ nbr, sms: true })) as PasCode - assert(pascode && pascode.sms === false && pascode.utc && pascode.utc > 0) - const pcode = await usr_r({ _id: uid }, { pcode: 1 }) - assert(pcode && pcode.pcode && pcode.pcode.code > 0) - const code = pcode.pcode.code - assert(null === await pos(p, "pas", json({ nbr, code: code + 1 }))) - assertEquals(p, { etag: null, pas: null }) - const pas = await pos(p, "pas", json({ nbr, code: code })) as Pas - assert(p.jwt && p.jwt.length > 0 && p.pas && p.pas.id.uid === uid) - const jwt = p.jwt - assertEquals(p.pas, pas) - assertEquals(await pos(p, "pas", ""), pas) - assertEquals(p, { etag: null, pas, jwt: null }) - assertEquals(await pos(p, "pas", ""), null) - await pos(p, "pas", json({ nbr, code: code })) - assertEquals(p.jwt, jwt) - assertEquals(await pos(p, "pas", json({ uid: p.pas.id.uid })), 1) - assertEquals(p, { etag: null, pas: null, jwt: null }) - assertEquals(await usr_r({ _id: uid }, { ptoken: 1 }), { _id: uid }) - await usr_d(uid) -}) - -Deno.test("pre", async () => { - const p: PasPos = {} - const actid = ["111111", "111112"] - const nbr = ["11111111111", "11111111112", "11111111113"] - const utc = Date.now() - const [adm1, adm2] = ["四川", "成都"] - await act_c({ _id: actid[0], exp: utc + 1000, act: "usrnew", ref: [1, 2] }) - await act_c({ _id: actid[1], exp: utc + 1000, act: "usrnbr", uid: 1 }) - assertEquals([1, null, 1, null], [ - await pos({}, "pre", json({ actid: actid[0], nbr: nbr[0], adm1, adm2 })), - await pos({}, "pre", json({ actid: actid[0], nbr: nbr[0], adm1, adm2 })), - await pos({}, "pre", json({ actid: actid[1], nbr: nbr[1], adm1, adm2 })), - await pos({}, "pre", json({ actid: actid[1], nbr: nbr[1], adm1, adm2 })), - ]) - assertEquals({ _id: 1, nbr: nbr[1] }, await usr_r({ _id: 1 }, { nbr: 1 })) - await aut_c({ _id: 1, aut: ["pre_usr"] }) - await pos(p, "pas", json({ nbr: nbr[1], sms: false })) - const pcode = await usr_r({ _id: 1 }, { pcode: 1 }) - await pos(p, "pas", json({ nbr: nbr[1], code: pcode?.pcode?.code })) - assert(2 === await pos(p, "pre", json({ nbr: nbr[2], adm1, adm2 }))) - await Promise.all([ - usr_d(1), aut_d(1), - usr_d(2), - ...actid.map(act_d), - ]) -}) - -Deno.test("pro", async () => { - const p: PasPos = {} - const nbr = ["11111111111", "11111111112", "11111111113"] - const utc = Date.now() - const recid = { uid: 3, aid: 1, utc } - assertEquals([ - await usr_c(nbr[0], [1, 2], "四川", "成都"), - await usr_c(nbr[1], [1, 2], "广东", "汕头"), - await usr_c(nbr[2], [2], "广东", "汕头"), - { sms: false }, { sms: false }, 1, 1, - recid, - ], await Promise.all([ - aut_c({ _id: 1, aut: ["pre_usr", "pre_soc", "pre_agd"] }), - aut_c({ _id: 2, aut: ["pre_usr", "pre_soc", "pre_agd"] }), - aut_c({ _id: 3, aut: ["pre_usr"] }), - ...[0, 2].map(n => pos(p, "pas", json({ nbr: nbr[n], sms: false }))), - soc_c("团体", [1, 2], "四川", "成都", ""), - agd_c("活动", [1, 2], "四川", "成都", ""), - rec_c(coll.worker, { _id: recid, rej: [], ref: [1, 2], exp: utc + 10000, rol: "worker" }) - ])) - const code = await Promise.all([1, 3].map(_id => usr_r({ _id }, { pcode: 1 }))) - await pos(p, "pas", json({ nbr: nbr[0], code: code[0]?.pcode?.code })) - assertEquals([null, 1, 0, 1, 1, 1, null, null], await Promise.all([ - pos(p, "pro", json({ re: "rej", uid: 2, pro: true })), - pos(p, "pro", json({ re: "ref", uid: 3, pro: true })), - pos(p, "pro", json({ re: "ref", sid: 1, pro: true })), - pos(p, "pro", json({ re: "rej", sid: 1, pro: true })), - pos(p, "pro", json({ re: "ref", aid: 1, pro: false })), - pos(p, "pro", json({ re: "rej", aid: 1, pro: true })), - pos(p, "pro", json({ re: "rej", rec: "worker", recid, pro: true })), - pos(p, "pro", json({ re: "ref", rec: "worker", recid, pro: true })), - ])) - await pos(p, "pas", json({ nbr: nbr[2], code: code[1]?.pcode?.code })) - assertEquals([null, 0, 1, null, null, null, 1, null], await Promise.all([ - pos(p, "pro", json({ re: "ref", uid: 1, pro: false })), - pos(p, "pro", json({ re: "ref", uid: 3, pro: false })), - pos(p, "pro", json({ re: "rej", uid: 3, pro: true })), - pos(p, "pro", json({ re: "rej", uid: 4, pro: true })), - pos(p, "pro", json({ re: "ref", sid: 1, pro: true })), - pos(p, "pro", json({ re: "rej", aid: 1, pro: true })), - pos(p, "pro", json({ re: "rej", rec: "worker", recid, pro: true })), - pos(p, "pro", json({ re: "ref", rec: "worker", recid, pro: true })), - ])) - await Promise.all([ - ...[1, 2, 3].map(usr_d), - ...[1, 2, 3].map(aut_d), - soc_d(1), - agd_d(1), - rec_d(coll.worker, recid), - ]) -}) - -Deno.test("put", async () => { - const p: PasPos = {} - const nbr = "11111111111" - const [uid, sid] = await Promise.all([ - usr_c(nbr, [1, 2], "四川", "成都"), - soc_c("社团", [2, 3], "广东", "汕头", "简介"), - ]) - await pos(p, "pas", json({ nbr, sms: false })) - const code = await usr_r({ _id: uid! }, { pcode: 1 }) - await pos(p, "pas", json({ nbr, code: code?.pcode?.code })) - await pos({ jwt: p.jwt }, "put", json({ uid, nam: "万大可", adm1: "广东", adm2: "汕头", intro: "简介" })) - assertEquals(await usr_r({ _id: uid! }, { nam: 1, adm1: 1, adm2: 1, intro: 1 }), { - _id: 1, adm1: "广东", adm2: "汕头", nam: "万大可", intro: "简介" - }) - await soc_u(sid!, { $set: { sec: [uid!] } }) - await pos({ jwt: p.jwt }, "put", json({ sid, nam: "社团二", intro: "简介二", adm1: "四川", adm2: "成都", sec: [2, 3], uid_max: 100 })) - assertEquals(await soc_r(sid!, { nam: 1, adm1: 1, adm2: 1, intro: 1, sec: 1, uid_max: 1 }), - { _id: sid!, nam: "社团", intro: "简介二", sec: [uid!], adm1: "广东", adm2: "汕头", uid_max: 128 } - ) -}) diff --git a/ismism.ts/tst/que.test.ts b/ismism.ts/tst/que.test.ts deleted file mode 100644 index e351b99..0000000 --- a/ismism.ts/tst/que.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { assert, assertEquals } from "https://deno.land/std@0.173.0/testing/asserts.ts" -import { coll, db } from "../src/db.ts" -import { agd_c } from "../src/eid/agd.ts" -import { rec_c } from "../src/eid/rec.ts" -import { soc_c, soc_u } from "../src/eid/soc.ts" -import { usr_c } from "../src/eid/usr.ts" -import { Agd, que, Soc, Usr } from "../src/pra/que.ts" - -await db("tst", true) - -const utc = Date.now() - -await Promise.all([ - await usr_c("11111111111", [1, 2], "四川", "成都"), - await usr_c("11111111112", [1, 2], "广东", "汕头"), - await usr_c("11111111113", [1, 2], "江苏", "苏州"), - await soc_c("社团一", [1, 2], "四川", "成都", "社团一"), - await soc_c("社团二", [1, 2], "江苏", "苏州", "社团二"), - await agd_c("活动一", [1, 2], "四川", "成都", "活动一"), - await agd_c("活动二", [1, 2], "江苏", "苏州", "活动二"), - soc_u(1, { $set: { uid: [1, 2, 3] } }), - soc_u(2, { $set: { uid: [3] } }), - rec_c(coll.worker, { _id: { uid: 1, aid: 1, utc }, exp: utc, rej: [], ref: [1, 2], rol: "sec" }), - rec_c(coll.worker, { _id: { uid: 2, aid: 2, utc }, exp: utc, rej: [], ref: [1, 2], rol: "worker" }), - rec_c(coll.work, { _id: { uid: 3, aid: 1, utc }, rej: [], ref: [1, 2], work: "work", msg: "work" }), - rec_c(coll.work, { _id: { uid: 1, aid: 2, utc }, rej: [], ref: [1, 2], work: "txt", nam: "txt", txt: "txt" }), - rec_c(coll.fund, { _id: { uid: 3, aid: 1, utc }, rej: [], ref: [1, 2], fund: 100, msg: "fund" }), -]) - -export function p( - obj: { - uid?: NonNullable["_id"], - sid?: NonNullable["_id"], - aid?: NonNullable["_id"], - adm1?: string, - adm2?: string, - } -) { - return new URLSearchParams(Object.entries(obj).map(([k, v]) => [k, `${v}`])) -} - -Deno.test("usr", async () => { - assertEquals({ ...await que("usr", p({ uid: 1 })), utc }, { - _id: 1, - ref: [1, 2], - adm1: "四川", - adm2: "成都", - rej: [], - nam: "1", - utc, - intro: "", - unam: [[1, "1"], [2, "2"]], - snam: [[1, "社团一"]], - nrec: { worker: 1, work: 1, fund: 0 } - }) -}) - -Deno.test("soc", async () => { - assertEquals({ ...await que("soc", p({ sid: 1 })), utc }, { - _id: 1, - nam: "社团一", - ref: [1, 2], - adm1: "四川", - adm2: "成都", - intro: "社团一", - rej: [], - utc, - sec: [], - uid_max: 128, - uid: [1, 2, 3], - res_max: 0, - res: [], - unam: [[1, "1"], [2, "2"], [3, "3"]], - nrec: { worker: 2, work: 2, fund: 1 } - }) - const [s1, s2, s] = await Promise.all([ - que("soc", p({ adm1: "四川" })), - que("soc", p({ adm2: "苏州" })), - que("soc", p({})), - ]) as [Soc[], Soc[], Soc[]] - assert(s.length === 2) - assertEquals([...s2, ...s1], s) -}) - -Deno.test("usr", async () => { - assertEquals({ ...await que("agd", p({ aid: 1 })), utc }, { - _id: 1, - nam: "活动一", - ref: [1, 2], - adm1: "四川", - adm2: "成都", - intro: "活动一", - rej: [], - utc, - detail: "", - budget: 0, - fund: 0, - expense: 0, - goal: [], - img: [], - res_max: 0, - unam: [[1, "1"], [2, "2"]], - nrec: { worker: 1, work: 1, fund: 1 } - }) - const [a1, a2, a] = await Promise.all([ - que("agd", p({ adm2: "成都" })), - que("agd", p({ adm1: "江苏" })), - que("agd", p({})), - ]) as [Agd[], Agd[], Agd[]] - assert(a.length === 2) - assertEquals([...a2, ...a1], a) -}) diff --git a/ismism.ts/ui/bind/article.ts b/ismism.ts/ui/bind/article.ts deleted file mode 100644 index 4613bca..0000000 --- a/ismism.ts/ui/bind/article.ts +++ /dev/null @@ -1,371 +0,0 @@ -import type { DocC } from "../../src/db.ts" -import type { Id } from "../../src/eid/typ.ts" -import { utc_medium } from "../../src/ont/utc.ts" -import type { Pas } from "../../src/pra/pas.ts" -import type { PasCode, UsrAct } from "../../src/pra/pos.ts" -import type * as Q from "../../src/pra/que.ts" -import { admsel, idnam, ida, idmeta, pro, label, btn, txt, goal } from "./section.ts" -import { bind, main, pos, que } from "./template.ts" -import { not_aut, not_pro } from "../../src/pra/con.ts" -import { not_actid, not_nbr } from "../../src/eid/is.ts" -import { hashchange, pas, paschange } from "./nav.ts" - -export function pasact( -) { - if (hashchange("pas")) return - if (pas) { - pos("pas", { uid: pas.id.uid }) - paschange(null) - } - - main.innerHTML = "" - const t = bind("pasact") - - const send = async () => { - if (not_nbr(t.nbr.value)) return alert("无效手机号") - t.nbr.readOnly = t.send.disabled = true - const sent = await pos("pas", { nbr: t.nbr.value, sms: location.hostname === "ismist.cn" }) - if (sent) { - const utc = sent.utc ? `\n上次发送:${utc_medium(sent.utc)}` : "" - t.hint.innerText = `验证码已发送,可多次使用\n一小时内不再重复发送${utc}` - t.pas.classList.remove("none") - } else { - t.hint.innerText = `手机号未注册\n输入居住地与注册激活码\n激活码只能使用一次,确认手机号无误` - admsel(t) - t.adm.classList.remove("none") - t.pre.classList.remove("none") - } - } - t.send.addEventListener("click", send) - - t.act.addEventListener("click", async () => { - if (not_actid(t.actid.value)) return alert("无效激活码") - t.actid.readOnly = t.act.disabled = t.adm1.disabled = t.adm2.disabled = true - const uid = await pos("pre", { actid: t.actid.value, nbr: t.nbr.value, adm1: t.adm1.value, adm2: t.adm2.value }) - if (uid) { - await send() - t.pas.classList.remove("none") - } else { - t.actid.readOnly = t.act.disabled = t.adm1.disabled = t.adm2.disabled = false - alert("无效激活码") - } - }) - - t.issue.addEventListener("click", async () => { - if (!t.code.checkValidity()) return alert("无效验证码") - t.code.readOnly = t.issue.disabled = true - const p = await pos("pas", { nbr: t.nbr.value, code: parseInt(t.code.value) }) - if (!p) { - t.code.readOnly = t.issue.disabled = false - return alert("无效验证码") - } - paschange(p) - usr(p.id.uid) - }) - - main.append(t.bind) -} - -export type Usr = Omit, "unam" | "snam"> & { - unam: Map, - snam: Map, -} - -export async function usr( - uid: Usr["_id"], -) { - if (hashchange(`${uid}`)) return - - const q = await que(`usr?uid=${uid}`) - if (!q) return idnull(`${uid}`, "用户") - const u: Usr = { ...q, unam: new Map(q.unam), snam: new Map(q.snam) } - - main.innerHTML = "" - const t = bind("usr") - - const pub = idmeta(pas, t, u) - idnam(t, `${uid}`, pub ? u.nam : "-冻结中-") - - if (pub) { - t.intro.innerText = u.intro.length > 0 ? u.intro : "无" - ida(t.soc, "s", u.snam) - t.rec.innerText = JSON.stringify(u.nrec) - } else[t.intro, t.soc, t.rec].forEach(el => el.classList.add("pubn")) - - if (pas) { - if (pas.id.uid === uid) { - t.put.addEventListener("click", () => put("用户", u)) - t.pas.addEventListener("click", () => pasact()) - if (not_aut(pas.aut, "pre_usr")) t.preusr.remove() - else t.preusr.addEventListener("click", () => pre("创建用户")) - if (not_aut(pas.aut, "pre_soc")) t.presoc.remove() - else t.presoc.addEventListener("click", () => pre("创建社团")) - if (not_aut(pas.aut, "pre_agd")) t.preagd.remove() - else t.preagd.addEventListener("click", () => pre("创建活动")) - t.pro.remove() - } else { - t.pos.remove() - t.pre.remove() - if (not_aut(pas.aut, "pre_usr") || not_pro(pas) || pas.ref.includes(uid)) - pro(pas, t, u) - else pro(pas, t, u, () => usr(u._id)) - } - } else { - t.pos.remove() - t.pre.remove() - t.pro.remove() - } - - main.append(t.bind) -} - -export type Soc = Omit, "unam"> & { - unam: Map, -} - -export async function soc( - sid?: Soc["_id"] -) { - if (hashchange(`s${sid ?? "oc"}`)) return - - let ss = sid ? [await que(`soc?sid=${sid}`)] : await que("soc") - ss = ss.filter(s => s) - if (sid && ss.length === 0) return idnull(`s${sid}`, "社团") - - main.innerHTML = "" - - for (const d of ss) { - if (!d) continue - - const t = bind("soc") - const s = { ...d, unam: new Map(d.unam) } - - const pub = idmeta(pas, t, s) - idnam(t, `s${s._id}`, s.nam) - - if (pub) { - ida(t.sec, "", s.unam, s.sec) - ida(t.uid, "", s.unam, s.uid) - label(t.res, `申请加入(${s.res.length}/${s.reslim}):`) - ida(t.res, "", s.unam, s.res) - t.intro.innerText = s.intro - t.rec.innerText = JSON.stringify(s.nrec) - } else[t.sec, t.uid, t.res, t.intro, t.rec].forEach(el => el.classList.add("pubn")) - - if (pas) { - const [np, na, ns, nr, nu] = [ - not_pro(pas), not_aut(pas.aut, "pre_soc"), - !s.sec.includes(pas.id.uid), - !s.res.includes(pas.id.uid), - !s.uid.includes(pas.id.uid) - ] - if (na || np) pro(pas, t, s) - else pro(pas, t, s, () => soc(s._id)) - if (na && ns) t.putsoc.remove() - else if (np) t.putsoc.disabled = true - else t.putsoc.addEventListener("click", () => put("社团", s)) - if (na) t.putsec.remove() - else if (np) t.putsec.disabled = true - if (!nu) t.putres.remove() - else { - const res = !s.res.includes(pas.id.uid) - btn(t.putres, res ? "申请加入" : "取消申请", !res || pub && s.res.length < s.reslim ? { - pos: () => pos("put", { sid: s._id, res }), refresh: () => soc(s._id) - } : undefined) - } - if (nu) t.putuid.remove() - else btn(t.putuid, t.putuid.innerText, { - confirm: "退出社团?", - pos: () => pos("put", { sid: s._id, uid: pas!.id.uid, pro: false }), - refresh: () => soc(s._id), - }) - } else { - t.put.remove() - t.pro.remove() - } - - main.append(t.bind) - } -} - -export type Agd = Omit, "unam"> & { - unam: Map, -} - -export async function agd( - aid?: Agd["_id"] -) { - if (hashchange(`a${aid ?? "gd"}`)) return - - let aa = aid ? [await que(`agd?aid=${aid}`)] : await que("agd") - aa = aa.filter(a => a) - if (aid && aa.length === 0) return idnull(`a${aid}`, "活动") - - main.innerHTML = "" - - for (const d of aa) { - if (!d) continue - - const t = bind("agd") - const a = { ...d, unam: new Map(d.unam) } - - const pub = idmeta(pas, t, a) - idnam(t, `a${a._id}`, a.nam) - - if (pub) { - goal(t, a) - t.intro.innerText = a.intro - t.rec.innerText = JSON.stringify(a.nrec) - } else[t.goal, t.intro, t.rec].forEach(el => el.classList.add("pubn")) - - if (a.budget > 0) { - t.fund.textContent = `${a.fund}` - t.budget.textContent = `${a.budget}` - t.expense.textContent = `${a.expense}` - const [fpct, epct] = [a.fund / a.budget, a.expense / a.budget].map(p => `${Math.round(p * 100)}%`) - t.fundbar.style.width = t.fundpct.textContent = fpct - t.expensebar.style.width = t.expensepct.textContent = epct - } - t.detail.href = a.detail - - if (pas) { - if (not_aut(pas.aut, "pre_agd") || not_pro(pas)) pro(pas, t, a) - else pro(pas, t, a, () => agd(a._id)) - if (pas.aid.sec.includes(a._id)) btn(t.putgoal, t.putgoal.innerText, not_pro(pas) ? undefined : { - prompt1: "输入目标名,为 2-16 个中文字符", - prompt2: "输入进度百分比,为 0-100 间的整数。留空将删除目标", - pos: (nam, pct) => { - if (!nam) return null - return pos("put", { aid: a._id, goal: nam, ...pct ? { pct: parseInt(pct) } : {} }) - }, - alert: "无效输入\n目标名是 2-16 个中文字符\n进度百分比是 0-100 间的整数\n最多设定 9 个目标", - refresh: () => agd(a._id) - }); else t.put.remove() - } else { - t.pro.remove() - t.put.remove() - } - - main.append(t.bind) - } -} - -function pre( - nam: "创建用户" | "创建社团" | "创建活动" -) { - if (!pas || hashchange(`${pas.id.uid}`)) return - - main.innerHTML = "" - const t = bind("pre") - - idnam(t, `${pas.id.uid}`, nam) - t.meta.innerText = `将作为推荐人${nam}` - admsel(t) - - switch (nam) { - case "创建用户": { - t.meta.innerText += `\n新用户可通过手机号登录、编辑用户信息` - t.pnam.parentElement?.remove() - t.intro.parentElement?.remove() - break - } case "创建社团": case "创建活动": { - t.nbr.parentElement?.remove() - txt(t.intro, "简介") - break - } default: { usr(pas.id.uid); return } - } - const { p, f } = { - p: () => ({ - nbr: t.nbr.value, adm1: t.adm1.value, adm2: t.adm2.value - }), f: usr, - ...nam === "创建社团" ? { - p: () => ({ - snam: t.pnam.value, adm1: t.adm1.value, adm2: t.adm2.value, intro: t.intro.value - }), f: soc, - } : {}, - ...nam === "创建活动" ? { - p: () => ({ - anam: t.pnam.value, adm1: t.adm1.value, adm2: t.adm2.value, intro: t.intro.value - }), f: agd, - } : {}, - } - btn(t.pre, t.pre.innerText, { - pos: () => pos>("pre", p()), - alert: `无效输入\n或${nam === "创建用户" ? "手机号" : "名称"}已注册`, - refresh: f, - }) - t.cancel.addEventListener("click", () => usr(pas!.id.uid)) - - main.append(t.bind) -} - -function put( - typ: "用户" | "社团" | "活动", - id: Usr | Soc | Agd, -) { - if (!pas) return - main.innerHTML = "" - const t = bind("put") - - idnam(t, `${id._id}`, `编辑${typ}信息`) - t.pnam.value = id.nam - admsel(t, id.adm1, id.adm2) - txt(t.intro, "简介", id.intro) - - let p - let r - if (typ === "用户") { - t.resmax.parentElement?.remove() - t.detail.parentElement?.remove() - p = () => pos("put", { - uid: id._id, nam: t.pnam.value, - adm1: t.adm1.value, adm2: t.adm2.value, - intro: t.intro.value.trim(), - }) - r = () => usr(id._id) - } else if (typ === "社团") { - t.resmax.value = `${(id as Soc).reslim}` - t.detail.parentElement?.remove() - if (not_aut(pas.aut, "pre_soc")) t.pnam.readOnly = t.adm1.disabled = t.adm2.disabled = true - p = () => pos("put", { - sid: id._id, nam: t.pnam.value, - adm1: t.adm1.value, adm2: t.adm2.value, - intro: t.intro.value.trim(), - res_max: parseInt(t.resmax.value), - }) - r = () => soc(id._id) - } else if (typ === "活动") { - t.resmax.value = `${(id as Agd).reslim}` - t.detail.value = (id as Agd).detail - if (not_aut(pas.aut, "pre_agd")) t.pnam.readOnly = t.adm1.disabled = t.adm2.disabled = true - p = () => pos("put", { - sid: id._id, nam: t.pnam.value, - adm1: t.adm1.value, adm2: t.adm2.value, - intro: t.intro.value.trim(), - res_max: parseInt(t.resmax.value), - detail: t.detail.value, - }) - r = () => agd(id._id) - } else return - btn(t.put, t.put.innerText, { - pos: p, - alert: "无效输入\n或名称已被占用", - refresh: r, - }) - t.cancel.addEventListener("click", r) - - main.append(t.bind) -} - -export function idnull( - id: string, - nam: string, -) { - main.innerHTML = "" - - const t = bind("idnull") - t.id.innerText = id - t.meta.innerText = `ismist#${id} 是无效${nam}` - - main.append(t.bind) -} diff --git a/ismism.ts/ui/bind/bind.ts b/ismism.ts/ui/bind/bind.ts deleted file mode 100644 index 4cfd43b..0000000 --- a/ismism.ts/ui/bind/bind.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { load } from "./nav.ts" - -load() diff --git a/ismism.ts/ui/bind/nav.ts b/ismism.ts/ui/bind/nav.ts deleted file mode 100644 index 779b3a0..0000000 --- a/ismism.ts/ui/bind/nav.ts +++ /dev/null @@ -1,47 +0,0 @@ -// deno-lint-ignore-file no-window-prefix -import { Pas } from "../../src/pra/pas.ts" -import { pasact, soc, usr, agd, idnull } from "./article.ts" -import { pas_a, pos } from "./template.ts" - -export let pas: Pas | null = null -export let hash = "" - -export async function paschange( - p?: Pas | null -) { - pas = p === undefined ? await pos("pas", {}) : p - if (pas) { - pas_a.innerText = pas.nam - pas_a.href = `#${pas.id.uid}` - } else { - pas_a.innerText = "用户登录" - pas_a.href = "#pas" - } -} - -export function hashchange( - h: string -): boolean { - if (hash === h || hash === "" && h === "agd") return false - location.href = `#${h}` - return true -} - -window.addEventListener("hashchange", () => { - hash = decodeURI(location.hash).substring(1) - if (hash === "pas") pasact() - else if (/^\d+$/.test(hash)) usr(parseInt(hash)) - else if (hash === "soc") soc() - else if (/^s\d+$/.test(hash)) soc(parseInt(hash.substring(1))) - else if (hash === "" || hash === "agd") agd() - else if (/^a\d+$/.test(hash)) agd(parseInt(hash.substring(1))) - else idnull(hash, "链接") -}) - -export async function load( -) { - console.log("ismism-20230204") - console.log(`\n主义主义开发小组!成员招募中!\n\n发送自我介绍至网站维护邮箱,或微信联系 728 万大可\n \n`) - await paschange() - window.dispatchEvent(new Event("hashchange")) -} diff --git a/ismism.ts/ui/bind/section.ts b/ismism.ts/ui/bind/section.ts deleted file mode 100644 index ce52c26..0000000 --- a/ismism.ts/ui/bind/section.ts +++ /dev/null @@ -1,177 +0,0 @@ -import type { Id } from "../../src/eid/typ.ts" -import type { Pas } from "../../src/pra/pas.ts" -import { utc_medium } from "../../src/ont/utc.ts" -import { adm } from "../../src/ont/adm.ts" -import { bind, pos, Template, utc_refresh } from "./template.ts" -import { is_aut } from "../../src/pra/con.ts" -import type { Usr, Soc, Agd } from "./article.ts" -import type { DocU } from "../../src/db.ts" -import { hash } from "./nav.ts" - -export function label( - el: HTMLElement, - s: string, -) { - const l = el.previousElementSibling as HTMLLabelElement - l.innerText = s -} - -export function btn< - T ->( - b: HTMLButtonElement, - s: string, - c?: { - prompt1?: string, - prompt2?: string, - confirm?: string, - pos: (p1?: string, p2?: string) => T, - alert?: string, - refresh: (r: NonNullable>) => void, - } -) { - b.innerText = s - if (c) b.addEventListener("click", async () => { - const p1 = c.prompt1 ? prompt(c.prompt1) : undefined - if (p1 === null) return - const p2 = c.prompt2 ? prompt(c.prompt2) : undefined - if (p2 === null) return - if (!c.confirm || confirm(c.confirm)) { - b.disabled = true - const r = await c.pos(p1, p2) - if (c.alert) { - if (r === null) { alert(c.alert); b.disabled = false; return } - } else { - if (!r || r <= 0) return - } - if (r || r === 0) setTimeout(() => c.refresh(r), utc_refresh) - } - }); else b.disabled = true -} - -function selopt( - sel: HTMLSelectElement, - opt: Iterable, -) { - sel.options.length = 0 - for (const op of opt) { - const t = document.createElement("option") - t.text = op - sel.add(t) - } -} - -export function txt( - t: HTMLTextAreaElement, - n: string, - s?: string, -) { - if (s) t.value = s - t.addEventListener("input", () => { - label(t, `${n}:(${t.value.length}/${t.maxLength} 个字符)`) - t.style.height = "auto" - t.style.height = `${t.scrollHeight}px` - }) - if (s) setTimeout(() => t.dispatchEvent(new Event("input")), 50) -} - -export function admsel( - t: Template["pasact" | "pre" | "put"], - adm1 = "江苏", - adm2 = "苏州" -) { - selopt(t.adm1, adm.keys()) - t.adm1.value = adm1 - selopt(t.adm2, adm.get(adm1)!) - t.adm2.value = adm2 - t.adm1.addEventListener("change", () => selopt(t.adm2, adm.get(t.adm1.value)!)) -} - -export function ida( - t: HTMLElement, - pf: "" | "s" | "a", - nam: Map, - id?: number[], -) { - if (!id) id = [...nam.keys()] - if (id.length === 0) return - id.forEach(id => { - const a = t.appendChild(document.createElement("a")) - a.href = `#${pf}${id}` - a.innerText = nam.get(id) ?? `${pf}${id}` - }) -} - -export function idmeta( - pas: Pas | null, - t: Template["usr" | "soc" | "agd"], - id: Usr | Soc | Agd, -): boolean { - const [rej, ref] = [id.rej.length >= 2, id.ref.length < 2] - const re: "rej" | "ref" | null = rej ? "rej" : ref ? "ref" : null - const { p }: { p?: boolean } = pas === null ? {} : { - ...t.tid === "usr" ? { p: is_aut(pas.aut, "pre_usr") || id._id === pas.id.uid } : {}, - ...t.tid === "soc" ? { p: is_aut(pas.aut, "pre_soc") || pas.sid.sec.includes(id._id) } : {}, - ...t.tid === "agd" ? { p: is_aut(pas.aut, "pre_agd") || pas.aid.sec.includes(id._id) } : {}, - } - const pub: boolean = re === null || p === true - - t.adm.innerText = `${id.adm1} ${id.adm2}` - t.utc.innerText = `${utc_medium(id.utc)}` - ida(t.rej, "", id.unam, id.rej) - ida(t.ref, "", id.unam, id.ref) - - if (rej) [t.rej, t.rejc].forEach(el => el.classList.add("red")) - if (ref) [t.ref, t.refc].forEach(el => el.classList.add("green")) - if (re === "rej") [t.id, t.proc].forEach(el => el.classList.add("red")) - else if (re === "ref") [t.id, t.proc].forEach(el => el.classList.add("green")) - - return pub -} - -export function idnam( - t: Template["usr" | "soc" | "agd" | "pre" | "put"], - id: string, - nam?: string, -) { - t.idnam.href = `#${id}` - t.id.innerText = id - if (hash === id) t.id.classList.add("active") - if (nam) t.nam.innerText = nam -} - -export function goal( - t: Template["agd"], - a: Agd -) { - for (const { nam, pct } of a.goal) { - const g = bind("goal") - g.nam.innerText = nam - if (pct === 0 || pct >= 100) g.pct.classList.add("gray") - if (pct >= 100) { - g.pct.textContent = "完成" - g.circle.remove() - } else { - g.pct.textContent = `${pct}%` - g.circle.style.setProperty("--pct", `${pct}`) - } - t.goal.append(g.bind) - } -} - -export function pro( - pas: Pas, - t: Template["usr" | "soc" | "agd"], - id: Usr | Soc | Agd, - refresh?: () => void, -) { - const [rej, ref] = [!id.rej.includes(pas.id.uid), !id.ref.includes(pas.id.uid)] - const p = (r: "rej" | "ref", p: boolean) => pos("pro", { - re: r, pro: p, - ...t.tid === "usr" ? { uid: id._id } : {}, - ...t.tid === "soc" ? { sid: id._id } : {}, - ...t.tid === "agd" ? { aid: id._id } : {}, - }) - btn(t.prorej, rej ? "反对" : "取消反对", refresh ? { pos: () => p("rej", rej), refresh } : undefined) - btn(t.proref, ref ? "推荐" : "取消推荐", refresh ? { pos: () => p("ref", ref), refresh } : undefined) -} diff --git a/ismism.ts/ui/bind/template.ts b/ismism.ts/ui/bind/template.ts deleted file mode 100644 index 08b5f88..0000000 --- a/ismism.ts/ui/bind/template.ts +++ /dev/null @@ -1,121 +0,0 @@ -export async function que( - q: string -) { - const r = await fetch(`/q/${q}`) - const etag = r.headers.get("etag")?.substring(3) - if (etag) utc_etag = parseInt(etag) - return r.json() as T -} - -export async function pos( - f: string, - b: Record, -) { - const res = await fetch(`/p/${f}`, { - method: "POST", - body: JSON.stringify(b) - }) - return res.json() as T -} - -export const utc_refresh = 500 -export let utc_etag = Date.now() -export const main = document.getElementById("main")! as HTMLDivElement -export const pas_a = document.getElementById("pas")! as HTMLAnchorElement - -const t: typeof document.createElement = (s: string) => document.createElement(s) -const svg = (s: S) => document.createElementNS("http://www.w3.org/2000/svg", s) - -const template = { - pasact: { - tid: "pasact" as const, - nbr: t("input"), send: t("button"), - adm: t("section"), adm1: t("select"), adm2: t("select"), - pre: t("section"), actid: t("input"), act: t("button"), - pas: t("section"), code: t("input"), issue: t("button"), - hint: t("section"), - }, - - usr: { - tid: "usr" as const, - idnam: t("a"), id: t("code"), nam: t("span"), - adm: t("span"), utc: t("span"), - rej: t("span"), ref: t("span"), - rejc: t("span"), refc: t("span"), proc: t("span"), - intro: t("p"), soc: t("p"), rec: t("p"), - pos: t("section"), put: t("button"), pas: t("button"), - pre: t("section"), preusr: t("button"), presoc: t("button"), preagd: t("button"), - pro: t("section"), prorej: t("button"), proref: t("button"), - }, - - soc: { - tid: "soc" as const, - idnam: t("a"), id: t("code"), nam: t("span"), - adm: t("span"), utc: t("span"), - rej: t("span"), ref: t("span"), - rejc: t("span"), refc: t("span"), proc: t("span"), - sec: t("p"), uid: t("p"), res: t("p"), intro: t("p"), rec: t("p"), - put: t("section"), putsoc: t("button"), putsec: t("button"), putuid: t("button"), putres: t("button"), - pro: t("section"), prorej: t("button"), proref: t("button"), - }, - - goal: { - tid: "goal" as const, - circle: svg("circle"), pct: svg("text"), nam: t("span"), - }, - - agd: { - tid: "agd" as const, - idnam: t("a"), id: t("code"), nam: t("span"), - adm: t("span"), utc: t("span"), - rej: t("span"), ref: t("span"), - rejc: t("span"), refc: t("span"), proc: t("span"), - fundbar: svg("rect"), expensebar: svg("rect"), - fund: svg("text"), fundpct: svg("text"), budget: svg("text"), - expense: svg("text"), expensepct: svg("text"), - detail: t("a"), - goal: t("p"), intro: t("p"), rec: t("p"), - pro: t("section"), prorej: t("button"), proref: t("button"), - put: t("section"), putagd: t("button"), putgoal: t("button"), - }, - - pre: { - tid: "pre" as const, - idnam: t("a"), id: t("code"), nam: t("span"), - meta: t("section"), pnam: t("input"), nbr: t("input"), - adm: t("section"), adm1: t("select"), adm2: t("select"), - intro: t("textarea"), - pre: t("button"), cancel: t("button"), - }, - - put: { - tid: "put" as const, - idnam: t("a"), id: t("code"), nam: t("span"), - pnam: t("input"), adm1: t("select"), adm2: t("select"), intro: t("textarea"), - resmax: t("input"), detail: t("input"), - put: t("button"), cancel: t("button"), - }, - - idnull: { - tid: "idnull" as const, - id: t("cod"), - meta: t("section") - } -} -export type Template = typeof template - -export function bind< - T extends keyof Template ->( - tid: T -): Template[T] & { bind: DocumentFragment } { - const temp = document.getElementById(tid) as HTMLTemplateElement - const t = temp.content.cloneNode(true) as DocumentFragment - const b = Object.fromEntries([ - ["bind", t], ...Object.keys(template[tid]).map(c => [ - c, t.querySelector(`.${c}`) as HTMLElement - ]) - ]) as Template[T] & { bind: DocumentFragment } - b.tid = tid - return b -} diff --git a/ismism.ts/ui/index/index.html b/ismism.ts/ui/index/index.html deleted file mode 100644 index 7cc6b03..0000000 --- a/ismism.ts/ui/index/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - 主义主义 - - - - - - - - - - - - -
- - - - - - - diff --git a/ismism.ts/ui/index/style.css b/ismism.ts/ui/index/style.css deleted file mode 100644 index 19ca822..0000000 --- a/ismism.ts/ui/index/style.css +++ /dev/null @@ -1,531 +0,0 @@ -:root { - --white: #fff; - --lightgray: #f1f1f1; - --gray: #9e9e9e; - --darkgray: #616161; - --black: #000; - --palered: #ffdddd; - --red: #f44336; - --green: #4CAF50; - --amber: #ffc107; - --purple: #673ab7; - - --small: 12px; - --normal: 15px; - --large: 18px; - - --w-max: 1400px; - --w-min: 360px; - --w-max-main: 1080px; -} - -.none { - display: none !important; -} - -html { - overflow-x: hidden; -} - -body { - min-width: 360px; - margin: 0; - padding: 0; - color: var(--black); - background: var(--lightgray); - font-family: Verdana, sans-serif; - font-size: var(--normal); - line-height: 1.5; -} - -hr { - width: 100%; - border: none; - margin: 6px; -} - -em { - font-style: normal; -} - -code { - font-family: monospace; - font-size: 1em; -} - -a { - color: inherit; - text-decoration: none; -} - -a:focus { - outline: none; -} - -nav { - overflow: scroll; - scrollbar-width: none; - scroll-snap-type: x mandatory; - margin: 0; -} - -nav::-webkit-scrollbar { - display: none; -} - -nav>menu { - position: relative; - display: flex; - width: max-content; - list-style: none; - padding: 0; - margin: 0 auto; - white-space: nowrap; - gap: 3px; -} - -nav>menu>li:first-child, -nav>menu>li:last-child { - display: block; - white-space: pre; - position: sticky; - min-width: 1ch; - box-shadow: 0 0 1ch 1ch var(--lightgray); - background: var(--lightgray); - z-index: 2; -} - -nav>menu>li:first-child { - left: 0; - margin-right: 2ch; -} - -nav>menu>li:last-child { - right: 0; - margin-left: 2ch; -} - -nav>menu>li>a { - scroll-snap-align: start; - scroll-margin-left: 2ch; - display: inline-flex; - white-space: nowrap; - overflow: hidden; - user-select: none; - background: none; - z-index: 1; -} - -article { - position: relative; - animation: scale 0.4s; - margin: 16px; - padding: 8px 16px; - background: var(--white); - box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset; -} - -@keyframes scale { - from { - transform: scale(0.25); - opacity: 0; - } - - to { - transform: scale(1); - opacity: 1; - } -} - -section { - display: block; - margin: 0; - padding: 0; -} - -section>label { - display: block; - width: 100%; - color: var(--gray); -} - -section>p { - display: block; - margin: 0; - padding: 1ch; -} - -section>span:empty::before { - color: var(--gray) !important; - content: "无"; -} - -section>p:empty::before { - padding: 1ch; - color: var(--gray); - content: "无"; -} - -section>textarea { - box-sizing: border-box; - display: block; - margin: 0; - padding: 1ch; - margin: 6px 0; - width: 100%; - font-size: 1em; - overflow: hidden; - resize: none; - outline: none; - border: 1px dotted var(--black); -} - -section>textarea:focus { - border: 1px solid var(--black); -} - -section>select { - font-size: 1em; - width: 12ch; - margin: 12px 0; - padding: 0.2ch 1ch; -} - -section>span>a:not(:first-child):before, -section>p>a:not(:first-child):before { - content: "、"; - color: initial; -} - -@media (hover: hover) { - - section>span>a:hover, - section>p>a:hover { - color: var(--amber); - } -} - -div#main { - max-width: 1080px; - margin: 0 auto; - padding: 0; -} - -section.flex { - display: flex; - margin-top: 6px; - flex-wrap: wrap; - justify-content: center; - align-items: center; - gap: 6px; -} - -section.flex>label, -section.flex>input, -section.flex>button, -section.flex>select { - box-sizing: border-box; - display: block; - justify-content: center; - align-items: center; - font-size: 1em; -} - -section.flex>label { - transform: translateY(0.75ch); -} - -section.flex>button { - flex: 1 1 10ch; - max-width: 24ch; - padding: 1ch; - background: var(--darkgray); - color: var(--lightgray); - border: none; - border-radius: 8px; -} - -section.flex>button:disabled { - background: var(--lightgray); - color: var(--darkgray); -} - -section.flex>button:focus { - outline: none; -} - -@media (hover: hover) { - section.flex>button:enabled:hover { - opacity: 0.65; - } -} - -section.flex>input { - flex: 10 1 10ch; - padding: 1ch; - max-width: 36ch; - border: none; - border-bottom: 1px dotted var(--black); - text-align: center; -} - -section.flex>input:focus { - outline: none; - border-bottom: 1px solid var(--black); -} - -section.flex>input:focus::placeholder { - color: transparent; -} - -section.flex>input:read-only { - background: var(--lightgray); - border: none; -} - -section.flex>select { - flex: 0 0 12ch; -} - -section.hint { - color: var(--gray); - text-align: center; - white-space: pre-line; -} - -section.meta { - padding: 1ch; - font-family: monospace; - color: var(--gray); - background: var(--lightgray); -} - -section.meta>span { - color: var(--black) -} - -section.meta>span.rejc, -section.meta>span.refc, -section.meta>span.proc { - color: var(--gray); -} - -section.meta>span.red { - color: var(--red) !important; -} - -section.meta>span.green, -section.meta>span.green:empty::before { - color: var(--green) !important; -} - -section.cover { - padding-top: 6px; - color: var(--darkgray); - border-top: 1px dotted var(--lightgray); - gap: 0; -} - -@media (max-width: 720px) { - section.cover>div { - width: 100%; - text-align: center; - } -} - -@media (min-width: 720px) { - section.cover>div { - flex-basis: 180px; - flex-grow: 1; - } - - section.cover>div:nth-child(1) { - text-align: left; - } - - section.cover>div:nth-child(2) { - text-align: center; - } - - section.cover>div:nth-child(3) { - text-align: right; - } -} - -section.cover>div>button { - font-size: 1em; - color: var(--darkgray); - background: none; - border: none; - cursor: pointer; -} - -section.cover>div>button:focus { - outline: none; -} - -@media (hover: hover) { - section.cover>div>button:hover { - color: var(--white) !important; - border-color: var(--darkgray) !important; - background: var(--darkgray) !important; - opacity: 0.7; - } -} - -section.cover>img { - width: 100%; - margin: 6px 0; - box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px; -} - -section.acct>div>:last-child { - float: right; -} - -section.acct>svg { - margin: 0.4em 0 0.2em 0; - box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px; -} - -section.acct>svg>rect:first { - fill: var(--lightgray); -} - -section.acct>svg>rect:not(:first-child) { - fill: var(--gray); -} - -section.acct>svg>text { - font-size: 1em; - font-family: monospace; - fill: var(--black); -} - -section.acct>svg>text.fund, -section.acct>svg>text.expense { - text-anchor: start; -} - -section.acct>svg>text.fundpct, -section.acct>svg>text.expensepct { - text-anchor: middle; -} - -section.acct>svg>text.budget { - text-anchor: end; -} - -section>p.goal:not(:empty) { - display: flex; - flex-wrap: wrap; - justify-content: space-around; - align-items: center; - gap: 6px; -} - -section>p.goal>div { - width: 160px; -} - -section>p.goal>div>svg { - filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, .4)); -} - -section>p.goal>div>svg>circle:first-child { - stroke: var(--gray); - stroke-width: 25px; - fill: var(--white); -} - -section>p.goal>div>svg>circle:nth-child(2) { - --pct: 0; - stroke: var(--lightgray); - stroke-width: 25px; - stroke-dasharray: 377px 377px; - stroke-dashoffset: calc(-377px * var(--pct) / 100); - fill: transparent; -} - -section>p.goal>div>svg>text { - text-anchor: middle; - font-size: 30px; - fill: var(--amber); -} - -section>p.goal>div>svg>text.gray { - fill: var(--gray) -} - -section>p.goal>div>span { - display: block; - font-size: var(--large); - color: var(--darkgray); - text-align: center; -} - -section>p.pubn:empty::before { - content: "-冻结中-" !important; -} - -a.idnam { - display: block; - font-size: 24px; -} - -a.idnam>code.id { - padding: 0.1em 8px; - border: 1px solid var(--black); - border-radius: 4px; - color: var(--black); -} - -a.idnam>code.id.active { - background: var(--darkgray); - color: var(--white); -} - -a.idnam>code.id.red { - border: none; - background: var(--red) !important; -} - -a.idnam>code.id.green { - border: none; - background: var(--green) !important; -} - -a.idnam>span.nam { - font-weight: bold; -} - -nav.main>menu { - border-bottom: 1px dotted var(--gray); -} - -nav.main a { - scroll-padding-left: -4ch; - display: inline-block; - font-size: var(--large); - color: var(--gray); - padding: 0 0.5ch; -} - -nav.main li.active>a { - color: var(--black); -} - -nav.main li.active>a>em { - color: var(--red); -} - -@media (hover: hover) { - nav.main a:hover { - color: var(--black); - opacity: 0.65; - } - - nav.main a:hover>em { - color: var(--red); - } -} diff --git a/ismism.ts/ui/index/template.html b/ismism.ts/ui/index/template.html deleted file mode 100644 index 51dd283..0000000 --- a/ismism.ts/ui/index/template.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/ismism.ts/ui/ui.ts b/ismism.ts/ui/ui.ts deleted file mode 100644 index 45c879d..0000000 --- a/ismism.ts/ui/ui.ts +++ /dev/null @@ -1,12 +0,0 @@ -const [style, template, index, bind] = await Promise.all([ - Deno.readTextFile("./ui/index/style.css"), - Deno.readTextFile("./ui/index/template.html"), - Deno.readTextFile("./ui/index/index.html"), - Deno.readTextFile("./ui/bind/bind.js"), -]) - -Deno.writeTextFileSync("../ui/index.html", index - .replace("", ``) - .replace("", template) - .replace("", ``) -)