From 1cbd77813130e811b8be46787e5a74d892121b84 Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Mon, 6 Oct 2025 16:59:18 +0200 Subject: [PATCH] feat(auth/user): Finished User Rework to handle Guest - Split userinfo APIs to their own service (`user`) - Added user service to nginx and docker-compose - Cleaned up package.json across the project to remove useless depedencies - Added word list for Guest username generation (source in file itself) - Reworked internal of `user` DB to not have a difference between "raw" id and normal ID (UUID) --- docker-compose.yml | 20 + nginx/conf/locations/user.conf | 4 + src/@shared/src/auth/index.ts | 2 +- src/@shared/src/database/mixin/user.ts | 18 +- src/auth/extra/login_demo.js | 2 +- src/auth/package.json | 3 +- src/auth/src/plugins/files/adjectives.txt | 1011 ++++++++ src/auth/src/plugins/files/nouns.txt | 2877 +++++++++++++++++++++ src/auth/src/plugins/words.ts | 40 + src/auth/src/routes/guestLogin.ts | 54 + src/auth/src/routes/otp.ts | 2 +- src/auth/src/routes/whoami.ts | 27 - src/package.json | 1 + src/user/.dockerignore | 2 + src/user/entrypoint.sh | 8 + src/user/extra/.gitkeep | 0 src/user/package.json | 36 + src/user/src/app.ts | 38 + src/user/src/plugins/README.md | 16 + src/user/src/plugins/sensible.ts | 11 + src/user/src/routes/info.ts | 56 + src/user/src/run.ts | 35 + src/user/tsconfig.json | 5 + src/user/vite.config.js | 51 + 24 files changed, 4273 insertions(+), 46 deletions(-) create mode 100644 nginx/conf/locations/user.conf create mode 100644 src/auth/src/plugins/files/adjectives.txt create mode 100644 src/auth/src/plugins/files/nouns.txt create mode 100644 src/auth/src/plugins/words.ts create mode 100644 src/auth/src/routes/guestLogin.ts delete mode 100644 src/auth/src/routes/whoami.ts create mode 100644 src/user/.dockerignore create mode 100644 src/user/entrypoint.sh create mode 100644 src/user/extra/.gitkeep create mode 100644 src/user/package.json create mode 100644 src/user/src/app.ts create mode 100644 src/user/src/plugins/README.md create mode 100644 src/user/src/plugins/sensible.ts create mode 100644 src/user/src/routes/info.ts create mode 100644 src/user/src/run.ts create mode 100644 src/user/tsconfig.json create mode 100644 src/user/vite.config.js diff --git a/docker-compose.yml b/docker-compose.yml index 8b18715..a3db5a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,6 +64,26 @@ services: environment: - JWT_SECRET=KRUGKIDROVUWG2ZAMJZG653OEBTG66BANJ2W24DTEBXXMZLSEB2GQZJANRQXU6JA - DATABASE_DIR=/volumes/database + + ############### + # USER # + ############### + user: + build: + context: ./src/ + args: + - SERVICE=user + # - EXTRA_FILES=user/extra + container_name: user + restart: always + networks: + - transcendance-network + volumes: + - sqlite-volume:/volumes/database + - static-volume:/volumes/static + environment: + - JWT_SECRET=KRUGKIDROVUWG2ZAMJZG653OEBTG66BANJ2W24DTEBXXMZLSEB2GQZJANRQXU6JA + - DATABASE_DIR=/volumes/database volumes: diff --git a/nginx/conf/locations/user.conf b/nginx/conf/locations/user.conf new file mode 100644 index 0000000..670546b --- /dev/null +++ b/nginx/conf/locations/user.conf @@ -0,0 +1,4 @@ +#forward the post request to the microservice +location /api/user/ { + proxy_pass http://user$uri; +} diff --git a/src/@shared/src/auth/index.ts b/src/@shared/src/auth/index.ts index 1a25d67..4bbdbb8 100644 --- a/src/@shared/src/auth/index.ts +++ b/src/@shared/src/auth/index.ts @@ -100,7 +100,7 @@ export const authPlugin = fp(async (fastify, _opts) => { JSON.stringify(makeResponse('notLoggedIn', 'auth.invalidKind')), ); } - const user = this.db.getUserFromName(tok.who); + const user = this.db.getUser(tok.who); if (isNullish(user)) { return res .clearCookie('token') diff --git a/src/@shared/src/database/mixin/user.ts b/src/@shared/src/database/mixin/user.ts index bb65edf..ccc4e1d 100644 --- a/src/@shared/src/database/mixin/user.ts +++ b/src/@shared/src/database/mixin/user.ts @@ -8,8 +8,9 @@ import * as bcrypt from 'bcrypt'; export interface IUserDb extends Database { getUser(id: UserId): User | undefined, getUserFromName(name: string): User | undefined, - getUserFromRawId(id: number): User | undefined, + getUser(id: string): User | undefined, getUserOtpSecret(id: UserId): string | undefined, + createUser(name: string, password: string | undefined, guest: boolean): Promise, createUser(name: string, password: string | undefined): Promise, setUserPassword(id: UserId, password: string | undefined): Promise, ensureUserOtpSecret(id: UserId): string | undefined, @@ -17,17 +18,6 @@ export interface IUserDb extends Database { }; export const UserImpl: Omit = { - /** - * Get a user from an [UserId] - * - * @param id the userid to fetch - * - * @returns The user if it exists, undefined otherwise - */ - getUser(this: IUserDb, id: UserId): User | undefined { - return this.getUserFromRawId(id); - }, - /** * Get a user from a username [string] * @@ -50,7 +40,7 @@ export const UserImpl: Omit = { * * @returns The user if it exists, undefined otherwise */ - getUserFromRawId(this: IUserDb, id: number): User | undefined { + getUser(this: IUserDb, id: string): User | undefined { return userFromRow( this.prepare('SELECT * FROM user WHERE id = @id LIMIT 1').get({ id, @@ -113,7 +103,7 @@ export const UserImpl: Omit = { }, }; -export type UserId = number & { readonly __brand: unique symbol }; +export type UserId = UUID; export type User = { readonly id: UserId; diff --git a/src/auth/extra/login_demo.js b/src/auth/extra/login_demo.js index c20f847..451986a 100644 --- a/src/auth/extra/login_demo.js +++ b/src/auth/extra/login_demo.js @@ -61,7 +61,7 @@ bOtpDisable.addEventListener('click', async () => { bWhoami.addEventListener('click', async () => { let username = ''; try { - const res = await fetch('/api/auth/whoami'); + const res = await fetch('/api/user/info/me'); const json = await res.json(); setResponse(json); if (json?.kind === 'success') {username = json?.payload?.name;} diff --git a/src/auth/package.json b/src/auth/package.json index 3d01f7c..01ccdd9 100644 --- a/src/auth/package.json +++ b/src/auth/package.json @@ -25,8 +25,7 @@ "@sinclair/typebox": "^0.34.40", "fastify": "^5.0.0", "fastify-cli": "^7.4.0", - "fastify-plugin": "^5.0.0", - "sharp": "^0.34.2" + "fastify-plugin": "^5.0.0" }, "devDependencies": { "@types/node": "^22.1.0", diff --git a/src/auth/src/plugins/files/adjectives.txt b/src/auth/src/plugins/files/adjectives.txt new file mode 100644 index 0000000..c3ada30 --- /dev/null +++ b/src/auth/src/plugins/files/adjectives.txt @@ -0,0 +1,1011 @@ +# https://raw.githubusercontent.com/taikuukaits/SimpleWordlists/refs/heads/master/Wordlist-Adjectives-Common-Audited-Len-3-6.txt +able +about +above +abuzz +ace +achy +acid +acned +acute +adept +adult +afire +afoot +afoul +aft +after +aged +agile +aging +aglow +ago +ahead +aided +airy +ajar +akin +alert +alien +alike +alive +all +alone +aloof +alpha +alto +amber +ample +angry +anti +antic +antsy +any +apart +apish +apt +arced +arch +arid +armed +ashen +ashy +askew +astir +atrip +attic +avian +avid +awake +aware +awash +away +awed +awful +awing +awned +awry +axial +azure +back +bad +baggy +baked +bald +balmy +bandy +bare +bared +basal +base +based +basic +bated +bats +batty +bay +beady +beamy +beat +beefy +beery +beige +bent +best +beta +bias +birch +bitty +black +blame +bland +blank +bleak +blear +blind +blond +blown +blue +bluff +blunt +boggy +bogus +bold +bone +boned +bonny +bony +boon +boozy +bored +born +boss +bossy +both +bound +bowed +boxed +boxy +brag +brash +brave +brief +briny +brisk +broad +broke +brown +brute +buff +buggy +built +bulgy +bulky +bully +bum +bumpy +burly +burnt +bush +bushy +bust +busty +busy +butch +calm +camp +campy +catty +cheap +chewy +chic +chief +civic +civil +clean +clear +cleft +close +cocky +cod +cold +color +comfy +comic +cool +coral +corny +cosy +coy +cozy +crazy +crisp +cross +cubic +cured +curly +curt +curvy +cushy +cut +cute +cyan +daft +daily +damn +damp +dandy +dank +dark +dated +dazed +dead +deaf +dear +deep +deft +deist +dense +dewy +dicey +dim +dingy +dinky +dire +dirt +dirty +dizzy +dodgy +domed +done +doped +dopey +dopy +dormy +dosed +down +downy +dozen +drab +drawn +dread +drear +dress +dried +droll +drunk +dry +dual +dud +due +dull +dumb +dummy +dusky +dusty +dyed +dying +each +eager +early +eased +east +easy +edged +edgy +eerie +eight +elder +elect +elfin +elite +empty +ended +epic +equal +even +every +evil +exact +extra +eyed +fab +faced +faded +faint +fair +fake +false +famed +fancy +far +fast +fat +fatal +fated +fazed +feral +few +fewer +fiery +fifth +fifty +filmy +final +fine +finer +fired +firm +first +fishy +fit +five +fixed +fizzy +flaky +flash +flat +fleet +flint +flip +fluid +flush +fly +foamy +focal +foggy +fond +fore +foul +found +four +foxy +frail +frank +free +fresh +fried +front +full +fumed +funky +funny +furry +fused +fussy +fuzzy +game +gaudy +gaunt +gawky +giant +giddy +gimpy +glad +glum +godly +going +gold +gone +good +gooey +goofy +gory +grand +great +green +grey +grim +grimy +gross +grown +gruff +gummy +gushy +gusty +gutsy +hairy +hale +half +halt +hammy +handy +happy +hard +hardy +harsh +hasty +hated +hazel +hazy +heard +heavy +hefty +held +here +hex +hexed +high +hilly +hind +hip +hired +hoar +hoary +hokey +holey +holy +home +homey +honey +horny +hot +huffy +huge +human +humid +hurt +husky +icky +icy +ideal +idle +iffy +ill +inane +inept +inert +inky +inner +ionic +irate +iron +jade +jaded +jaggy +jawed +jazzy +jet +joint +jolly +jowly +juicy +jumbo +jumpy +just +kempt +key +keyed +khaki +kin +kind +kinky +known +kooky +laced +lacy +laid +lame +lank +lanky +large +last +late +later +lax +lay +lazy +leafy +leaky +lean +least +left +legal +less +level +light +like +liked +limp +lined +lit +live +liver +livid +loamy +local +loco +lofty +lone +long +loony +loopy +loose +lossy +lost +loud +lousy +loved +low +lowly +loyal +lucid +lucky +lumpy +lunar +lurid +lush +lusty +lyric +macho +macro +mad +made +magic +main +major +male +mangy +manic +manly +many +mass +matt +matte +mauve +mealy +mean +meaty +meek +meet +mere +merry +messy +metal +micro +mild +milky +mimic +mined +mini +minor +mint +minty +minus +mired +mirky +misty +mixed +mock +mod +modal +model +moist +molar +moldy +mono +moody +moony +moot +moral +more +mossy +most +mothy +motor +mousy +moved +mown +much +mucky +muddy +muggy +mum +mural +murky +mushy +musky +must +musty +mute +muted +naive +nary +nasal +nasty +natal +natty +naval +near +neat +needy +nervy +new +newsy +next +nice +nifty +nigh +nine +ninth +noble +noisy +none +north +nosed +noted +novel +nubby +numb +nuts +nutty +oaken +oaten +obese +odd +oiled +oily +okay +old +olden +older +olive +one +only +oozy +open +optic +oral +other +out +outer +oval +over +overt +owing +own +owned +pagan +paid +pale +palmy +pass +past +pasty +pat +paved +peaky +peaty +pedal +pent +peppy +perky +pert +pesky +pet +petty +phony +piano +picky +pied +piggy +pilar +pink +plain +plane +plumb +plump +plus +plush +polar +poor +pop +port +posed +posh +potty +pricy +prim +prior +privy +prize +prone +proof +prosy +proud +pubic +pudgy +puff +puffy +pulpy +punk +puny +pupal +pure +pushy +quack +quasi +quick +quiet +rabid +radio +rainy +rapid +rare +rash +raspy +ratty +raw +ready +real +rear +red +regal +retro +rich +rife +right +rigid +riled +ripe +risen +risky +ritzy +roast +robed +rocky +roomy +ropey +rose +rosy +rough +round +rowdy +royal +ruby +rude +ruled +rum +rummy +runic +runny +runty +rural +rush +rushy +rust +rusty +rutty +sad +safe +sage +said +salt +salty +same +sandy +sane +sappy +sassy +saute +saved +scaly +scant +scary +scrub +seamy +sear +seedy +self +sent +seven +sewed +sewn +shady +shaky +sham +sharp +shed +sheer +shiny +short +shot +showy +shut +shy +sick +side +sign +silky +silly +silty +sissy +six +sixth +sixty +size +sized +skew +skim +slack +slain +slaty +slav +sleek +slick +slim +slimy +slow +sly +small +smart +smoky +smug +snaky +sneak +snide +snowy +snub +snuff +snug +soapy +sober +soft +soggy +solar +sold +sole +solid +solo +some +sooty +sore +sorry +sound +soupy +sour +south +sown +spare +spent +spicy +spiky +spiny +splay +split +spry +spumy +squab +squat +stagy +stale +star +stark +steep +stern +stiff +still +stock +stone +stony +stout +straw +stray +stuck +stung +suave +such +sudsy +sulky +sunk +sunny +super +sure +surly +sweet +swell +swept +swift +swish +sworn +tabby +taboo +tacky +taken +talky +tall +tame +tamed +tan +tangy +taped +tardy +tart +tasty +tawny +teal +ten +tenor +tense +tenth +tepid +terse +testy +thick +thin +third +three +tidal +tidy +tied +tight +tiled +timed +timid +tinny +tiny +tipsy +tired +toed +token +tonal +toned +tonic +top +tops +torn +total +tough +toxic +tried +trig +trim +trite +true +tubby +tubed +tumid +twee +twin +two +ugly +ultra +uncut +under +undue +unfed +unfit +union +unlit +unwed +upper +upset +urban +used +usual +utter +vague +vain +valid +vapid +vast +viral +vital +vivid +vocal +void +wacky +warm +wary +washy +waste +wavy +waxed +waxen +waxy +weak +weary +weedy +weeny +weepy +weird +well +welsh +west +wet +whiny +white +whole +wide +wild +wily +wimpy +windy +wired +wiry +wise +wispy +witty +wonky +woody +wooly +woozy +wordy +wormy +worn +worse +worst +worth +wound +woven +wrong +wroth +wry +young +yucky +yummy +zany +zero +zesty +zippy +zonal diff --git a/src/auth/src/plugins/files/nouns.txt b/src/auth/src/plugins/files/nouns.txt new file mode 100644 index 0000000..bc62c30 --- /dev/null +++ b/src/auth/src/plugins/files/nouns.txt @@ -0,0 +1,2877 @@ +# https://raw.githubusercontent.com/taikuukaits/SimpleWordlists/refs/heads/master/Wordlist-Nouns-Common-Audited-Len-3-6.txt +ace +ache +acid +acme +acorn +acre +act +actor +add +adder +adept +advil +afro +agave +age +aged +agent +agony +ailey +aim +aioli +air +aisle +akron +alarm +album +ale +alert +algae +alias +alibi +alien +alley +alloy +ally +aloe +alpha +alps +altar +amber +amigo +amino +amish +ammo +amp +angel +anger +angle +angst +angus +anime +ankle +annex +anole +ant +ante +antic +anvil +ape +apex +aphid +apple +april +apron +aqua +arbor +arc +arch +area +arena +argon +argus +ark +arm +armor +arms +army +aroma +array +arrow +arson +art +ascot +aspen +asset +ate +atom +attic +audio +audit +auger +aunt +aunty +aura +auto +award +awe +awl +axe +axiom +axis +axle +azure +baby +back +bacon +bad +badge +bag +bagel +bail +bait +baker +bale +balk +ball +balm +ban +band +bane +banjo +bank +banks +bar +barb +bard +barge +bark +barn +baron +bars +base +bash +basic +basil +basin +basis +bass +bat +batch +bath +baton +bay +bayou +beach +bead +beads +beak +beam +bean +bear +beard +beast +beat +beats +bed +bee +beech +beef +beep +beer +beet +begin +beige +being +belch +bell +belly +belt +bench +bend +bends +bent +beret +berry +bet +beta +bevel +bevy +bias +bib +bible +bid +bidet +bike +biker +bill +bin +bind +bingo +biome +biped +birch +bird +birth +bison +bit +bite +biter +black +blade +blame +blank +blast +blaze +blend +blimp +blind +bling +blink +blip +bliss +blitz +bloat +blob +block +blog +bloke +blond +blood +bloom +blow +blue +blues +bluff +blur +blurb +blush +boa +boar +board +boast +boat +bod +body +bog +bogey +boil +bold +bolt +bomb +bond +bone +boner +bones +bong +bongo +bonus +boo +book +boom +boon +boost +boot +booth +booty +booze +bore +borer +born +boss +bot +botch +bound +bow +bowel +bowl +bowls +box +boxer +boy +bra +brace +brag +braid +brail +brain +brake +bran +brand +brass +brat +brave +bravo +brawl +brawn +bread +break +breed +brew +briar +bribe +brick +bride +brie +brief +brim +brine +brink +brit +brits +britt +broad +broil +brood +brook +broom +broth +brow +brown +brunt +brush +brute +buck +bud +buddy +budge +buff +bug +buggy +bugle +build +bulb +bulge +bulk +bull +bully +bum +bump +bun +bunch +bung +bunk +bunny +buns +bunt +buoy +bur +burn +burns +burp +burst +bus +bush +buss +bust +buy +buyer +buzz +bye +bylaw +byte +cab +cabin +cable +cabot +cache +caddy +cadet +cafe +cage +cager +cake +calf +call +calm +cam +camel +camp +can +canal +candy +cane +cap +cape +caper +car +carat +card +cards +care +caret +cargo +carp +carry +cart +case +cash +cask +cast +caste +cat +catch +caulk +cause +cave +cavil +caw +cease +cedar +cell +cello +cent +chaff +chain +chair +chalk +champ +chant +chaos +chap +chard +charm +chart +chase +chasm +chat +cheat +check +cheek +cheep +cheer +chef +chess +chest +chew +chic +chick +chief +child +chill +chime +chimp +chin +chip +chips +chirp +chit +chive +chock +choir +choke +choky +chomp +chop +chord +chore +chow +chuck +chug +chum +chump +chunk +churn +chute +cider +cigar +cinch +cite +city +clack +claim +clam +clamp +clams +clan +clang +clank +clap +clash +clasp +class +clay +clean +clear +cleat +cleft +clerk +click +cliff +climb +cling +clip +cloak +clock +clog +clone +close +clot +cloth +cloud +clout +clove +clown +club +cluck +clue +clump +clunk +coach +coal +coast +coat +cobra +cocoa +cod +code +cog +coil +coin +coke +cola +cold +colon +color +colt +coma +comb +combo +come +comet +comic +comma +conch +condo +cone +coney +conk +cook +cool +coot +cop +cope +copy +coral +cord +cords +core +cork +corn +corp +corps +cost +costs +cosy +cot +couch +cough +count +court +cove +coven +cover +cow +cowl +cows +cozy +crab +crabs +crack +craft +cramp +crane +crank +crash +crate +crawl +craze +crazy +creak +cream +cred +cree +creed +creek +creep +crepe +cress +crest +crew +crib +crime +crimp +crisp +croak +crock +crook +crop +cross +crow +crowd +crown +crud +crude +crumb +crush +crust +crux +cry +crypt +cub +cubby +cube +cubit +cue +cuff +cull +cult +cup +curb +curd +cure +curl +curry +curse +curve +cut +cyan +cycle +cynic +dab +daily +dairy +daisy +dame +damp +dance +dandy +dane +dare +dark +dart +darts +dash +data +date +dawn +day +days +daze +dead +deaf +deal +dean +dear +death +debit +debt +debut +decal +decay +deck +decor +decoy +deed +deeds +deep +deer +delay +deli +delta +demo +demon +denim +dent +depot +depth +derby +desk +detox +deuce +devil +dew +dial +diary +dibs +dice +diet +dig +digit +digs +dill +dime +diner +ding +dip +dirt +disc +disco +dish +disk +ditch +ditto +dive +diver +dock +dodge +dog +dogma +doll +dolly +dolt +dome +donor +donut +doom +door +dope +dork +dorm +dot +doubt +dough +dove +dowel +down +dozen +dozer +draft +drag +drain +drama +drape +draw +dread +dream +dress +drew +drier +drift +drill +drink +drip +drive +drone +drool +drop +drove +drug +druid +drum +dry +dryer +duck +duct +due +duel +duet +dug +dunce +dune +dunk +dusk +dust +duty +dye +dyer +dying +eager +eagle +ear +earth +ease +easel +east +eater +eats +echo +edge +eel +egg +eggs +ego +eight +elbow +elder +elect +elf +elite +elk +elm +elves +email +ember +empty +emu +end +enemy +entry +envy +epic +epoxy +equal +era +error +essay +eve +even +event +evil +exam +exile +exit +extra +eye +eyes +fable +face +facet +fact +fad +fade +faint +fair +fairy +faith +fake +fall +falls +fame +fan +fancy +fang +far +farce +fare +farm +fast +fat +fate +fault +favor +fawn +fax +fear +feast +feat +fed +fee +feed +feel +felt +femur +fence +fern +ferry +fetch +feud +fever +few +fib +fiber +field +fiend +fifth +fifty +fig +fight +file +filet +fill +film +filth +final +finch +find +fine +fire +firm +first +fish +fist +fit +five +fiver +fives +fix +fixer +fizz +flag +flair +flak +flake +flame +flank +flap +flaps +flare +flash +flask +flat +flats +flaw +flea +fleet +flesh +flex +flick +flier +flies +fling +flint +flip +flirt +float +flock +flood +floor +flop +floss +flour +flow +flu +flub +fluff +fluid +fluke +flume +flush +flute +flux +fly +flyer +foam +focus +fog +foil +fold +folk +folks +folly +font +food +fool +foot +force +forge +fork +form +fort +forth +forty +forum +foul +found +four +fowl +fox +foyer +frail +frame +frat +fraud +fray +freak +free +freon +fret +friar +fries +frill +frisk +frizz +frog +front +frost +froth +frown +fruit +fry +fryer +fudge +fuel +full +fume +fumes +fun +fund +funds +fungi +funk +funny +fur +fury +fuse +fuss +futon +fuze +fuzz +gag +gage +gain +game +gamma +gap +gape +gas +gash +gasp +gate +gates +gator +gauge +gavel +gawk +gaze +gear +gecko +geek +gel +gem +gene +genie +genoa +genre +gent +germ +ghost +ghoul +giant +gift +gild +gimp +gin +gipsy +girl +gist +give +given +giver +gizmo +glad +glade +gland +glans +glare +glass +glaze +gleam +glee +glide +glint +globe +gloom +glory +gloss +glove +glow +glue +gnat +gnome +goal +goat +going +gold +golem +golf +goner +goo +good +goof +goofy +goon +goose +goth +gouge +gown +grab +grace +grad +grade +graft +grail +grain +gram +grand +grant +grape +graph +grasp +grass +grate +grave +gravy +gray +graze +great +greed +green +grey +grid +grief +grill +grime +grin +grind +grip +gripe +grit +grits +groan +groom +gross +group +grove +growl +grub +gruel +grump +grunt +guard +guess +guest +guide +guild +guilt +gulch +gulf +gull +gulp +gum +gun +guppy +guru +gush +gust +gut +guts +guy +gym +habit +hack +hag +hail +hair +half +hall +halo +halt +ham +hand +hands +handy +hang +hare +harp +hash +haste +hat +hatch +hate +hater +haunt +have +haven +havoc +hawk +hay +haze +hazel +head +heap +heaps +heart +heat +heavy +hedge +heed +heel +heft +heir +helix +hell +hello +helm +help +hem +hemp +hen +herb +herd +here +hero +hex +hick +hide +high +hike +hiker +hill +hilt +hind +hinge +hint +hip +hippo +hippy +hire +hiss +hit +hitch +hive +hives +hoagy +hoard +hoax +hob +hobby +hobo +hog +hoist +hold +hole +home +honey +honk +honor +hoof +hook +hooks +hoop +hoops +hoot +hop +hope +hops +horde +horn +horse +hose +host +hotel +hound +hour +hours +house +howl +hub +hue +huff +hug +hula +hulk +hull +hum +human +humor +hump +humus +hunch +hunk +hunt +hurl +hurry +hurt +hush +husk +husky +hut +hydra +hyena +hymn +hype +ibis +ice +icing +icon +idea +ideal +idiom +idiot +idle +idler +idol +igloo +iglu +ill +image +imp +inch +index +info +ingot +ink +inlet +inn +input +intro +ion +iris +iron +irony +isle +issue +itch +ivory +ivy +jab +jack +jacks +jail +jam +jamb +jar +java +jaw +jay +jazz +jean +jeans +jeep +jeer +jello +jelly +jest +jet +jetty +jewel +jig +jive +job +jock +jog +join +joint +joist +joke +joker +jolly +jolt +joust +joy +judge +jug +juice +juke +jump +junk +junky +juror +jury +kale +kayak +kazoo +kebab +keen +keep +keg +kelp +key +kick +kid +kiddy +kiln +kilo +kilt +kin +kind +king +kiss +kit +kite +kitty +kiwi +knack +knee +kneel +knell +knife +knit +knob +knock +knot +know +koala +krill +lab +label +labor +lace +lack +lad +ladle +lady +lag +lair +lake +lamb +lame +lamp +lance +land +lane +lap +lapel +lapse +lard +large +larva +laser +lash +lass +lasso +last +lat +latch +latex +lathe +latte +laugh +lava +law +lawn +laws +lay +layer +layup +leach +lead +leaf +leak +lean +leap +lear +lease +leash +least +leave +ledge +leech +leeds +leek +leer +left +lefty +leg +lego +legs +lemon +lemur +lens +lent +let +level +lever +liar +libel +lick +lid +lie +lied +life +lift +light +like +lilac +limb +limbo +lime +limit +limp +line +linen +liner +link +links +lint +lion +lip +lisp +list +lit +liter +liver +llama +loach +load +loads +loaf +loan +lob +lobby +lobe +local +lock +lodge +loft +log +logic +logo +loner +look +loom +loon +loony +loop +loot +lord +loser +loss +lost +lot +lots +lotto +lotus +love +lover +low +lower +luck +lump +lunch +lung +lure +lush +lying +mace +macro +madam +mafia +magi +magic +magma +maid +mail +main +major +maker +male +malt +mam +mama +mamba +mambo +mamma +man +mane +mango +mania +manor +map +maple +march +mare +mark +marks +mars +marsh +mash +mask +mass +mast +mat +match +mate +mates +math +maths +max +maxim +may +mayo +mayor +maze +meal +mean +means +meat +medal +medic +meet +meld +melee +melon +melt +memo +men +mend +menu +meow +mercy +merit +mesh +mess +metal +meter +meth +metro +might +mile +milk +mill +mills +mimer +mimic +min +mince +mind +mine +miner +mini +mink +minor +mint +minus +miser +miss +mist +mite +miter +mitt +mix +mixer +moan +moat +mob +mocha +mock +mod +modal +mode +model +modem +mogul +mojo +molar +mold +mole +molt +mom +momma +mommy +money +monk +month +moo +mooch +mood +moody +moon +moose +mop +mope +moped +moral +morse +moss +motel +moth +motor +motto +mould +mound +mount +mouse +mouth +move +mover +movie +mow +mucus +mud +muff +mug +mulch +mule +mum +mummy +munch +mural +muse +mush +music +musk +must +mute +mutt +mylar +nacho +name +namer +names +nanna +nap +nasal +navy +neck +need +needy +neon +nepal +nerd +nerve +nest +net +news +newt +nick +niece +night +nine +niner +ninja +ninth +noble +nod +node +noise +nomad +none +nook +noon +noose +north +nose +notch +note +noun +nudge +nuke +nun +nurse +nut +nylon +oaf +oak +oar +oasis +oat +oates +oath +ocean +octet +odds +ode +odor +offer +ogre +oil +oiler +oink +okay +old +oldie +olive +omega +omen +one +onion +onset +ooze +open +optic +oral +orange +orb +orbit +orca +order +ore +oreo +organ +ounce +out +oval +oven +over +owl +owner +oxbow +oxen +ozone +pace +pacer +pack +pact +pad +page +pager +pail +pain +pains +paint +pair +pal +pale +palm +pan +panda +pane +panel +panic +pansy +pant +pants +papa +paper +par +park +parks +part +parts +party +pass +past +pasta +paste +pat +patch +path +patio +pause +pave +paw +pawn +pay +payer +peace +peach +peak +pear +pearl +pecan +pedal +peek +peel +peer +peg +pelt +pen +penny +perch +peril +perk +pesto +pet +petal +petty +phase +phone +photo +piano +pick +pie +piece +pier +pig +piggy +pigmy +pike +pile +piles +pill +pimp +pin +pinch +pine +ping +pink +pinky +pinot +pint +pipe +pit +pita +pitch +pitt +pity +pivot +pixel +pizza +place +plaid +plain +plan +plane +plank +plant +plate +play +plaza +plea +plier +plot +plow +ploy +pluck +plug +plum +plumb +plume +plump +plus +plush +plyer +pod +poem +poet +point +poke +poker +pole +poll +polls +pond +pong +pony +pooch +poof +pool +poor +pop +poppy +porch +pore +pork +port +pose +poser +post +pot +pouch +pound +power +prank +prawn +press +prey +price +pride +prime +prism +prize +pro +probe +prom +promo +proof +prop +props +prose +prowl +prune +pry +pub +puck +puff +pug +pull +pulp +pulse +puma +pump +pun +punch +punk +punks +punt +pup +pupil +puppy +purge +purse +push +put +putt +putty +quack +quad +quake +qualm +quart +queen +query +quest +quick +quid +quiet +quilt +quirk +quirt +quiz +quota +quote +race +racer +rad +radar +radio +raft +rafts +rag +rage +raid +rail +rails +rain +raise +rake +rally +ram +ramp +ranch +range +rank +rant +rap +rapid +rash +rat +rate +rates +ratio +raw +ray +razor +razz +reach +read +ready +real +realm +ream +rear +rebel +red +reed +reef +reek +reel +reign +relay +relic +rent +reply +reset +resin +rest +retro +revel +rhino +rhyme +rib +rice +ricer +rich +ride +rider +ridge +riff +rifle +rift +rig +right +rim +rind +ring +rings +rink +rinse +riot +rip +rise +riser +risk +rite +rival +river +roach +road +roads +roar +roast +robe +robin +robot +rock +rod +rodeo +rogue +role +roll +room +rooms +roost +root +roots +rope +rose +rot +rotor +rouge +rough +round +route +rover +row +rowdy +rower +royal +rub +rube +ruby +rug +rugby +ruin +rule +ruler +rum +rummy +rumor +run +rune +rung +runt +ruse +rush +rust +rut +saber +safe +sag +saga +sage +sail +saint +salad +sale +salem +sales +salon +salsa +salt +same +sand +sands +sang +sash +sass +sauce +sauna +save +saver +savor +saw +say +scale +scan +scar +scare +scarf +scene +scent +scold +scone +scoop +scope +score +scorn +scout +scrap +sea +seal +seam +seat +seats +sect +sedan +see +seed +seek +seer +self +sell +sense +serum +serve +servo +set +setup +seven +shack +shade +shake +sham +shame +shank +shape +shard +share +shark +sharp +shave +shawl +shed +sheep +sheet +shelf +shell +shift +shill +shim +shin +ship +shirt +shoe +shoes +shop +shore +shot +shove +show +shred +shrub +shrug +shy +sick +siege +sigh +sight +sign +silk +silks +silly +silo +sin +sink +sinus +sip +sir +siren +six +sixer +sixth +sixty +size +ski +skid +skier +skill +skim +skin +skip +skirt +skit +skull +skunk +sky +slab +slack +slag +slain +slam +slang +slant +slap +slash +slate +slave +slaw +sled +sleep +sleet +slew +slews +slice +slick +slide +slime +sling +slip +slit +slob +slope +slot +sloth +slug +slum +slump +slur +slush +smack +small +smart +smash +smear +smell +smelt +smile +smirk +smith +smock +smog +smoke +snack +snag +snail +snake +snap +snare +snarl +sneak +sniff +snipe +snore +snort +snot +snow +snug +soak +soap +soar +sob +sock +sofa +softy +soil +sole +solid +son +sonar +song +sonny +soot +sooth +sore +sort +soul +sound +soup +sour +south +spa +space +spade +spam +span +spar +spare +spark +spasm +spat +spawn +speed +spell +spelt +spice +spike +spill +spin +spit +spite +splat +split +spoil +spoke +spoof +spook +spool +spoon +spore +sport +spot +spots +spout +spray +spree +spud +spur +spurt +spy +squat +squid +stab +stack +staff +stag +stage +stain +stair +stake +stalk +stall +stamp +stand +star +stare +start +stash +state +stay +stays +steak +steal +steam +steed +steel +steer +stem +step +steps +stern +stew +stick +stiff +still +stilt +sting +stink +stint +stir +stock +stoic +stomp +stone +stool +stoop +stop +stops +store +stork +storm +story +stove +strap +straw +stray +strip +strum +strut +stub +stud +study +stuff +stump +stunt +style +sub +suds +sugar +suit +suite +sum +sumer +sun +sung +super +surf +surge +sushi +sutra +swab +swag +swamp +swan +swap +swarm +sway +sweat +sweep +sweet +swell +swift +swim +swine +swing +swipe +swirl +swish +syrup +table +tack +taco +tact +tad +taffy +tag +tail +tails +take +taker +tale +talk +talks +tall +tally +talon +tan +tank +tap +tape +taps +tar +tarp +tart +task +taste +taunt +tax +taxer +taxi +taxis +tea +teach +teal +team +tear +tears +tease +teen +teens +teeth +tell +temp +tempo +ten +tense +tent +tenth +term +terms +test +text +thaw +theft +theme +then +there +theta +thick +thief +thigh +thing +think +third +thorn +three +throw +thud +thug +thumb +tick +tide +tidy +tie +tier +tiger +tilde +tile +till +time +timer +times +timid +tin +tint +tip +tire +titan +title +toad +toady +toast +today +toe +toil +token +toll +tomb +tome +ton +tone +toner +tongs +tonic +tons +tool +toon +toot +tooth +top +topic +torch +torso +toss +total +tote +totem +touch +tough +tour +tours +tow +towel +tower +town +towny +toxin +toy +trace +track +trade +trail +train +trait +trap +trash +tray +tread +treat +tree +trek +trend +triad +trial +trick +trim +trio +trip +troll +troop +trot +trout +truce +truck +true +trump +trunk +trust +truth +try +tub +tuba +tube +tuck +tug +tulip +tummy +tumor +tuna +tune +tuner +tunic +turf +turn +tush +tusk +tutor +twine +twins +twirl +twist +two +tying +type +typo +udder +ulcer +uncle +union +unit +unity +upper +upset +urn +usage +use +user +usher +using +valet +valor +value +valve +van +vase +vat +vault +vegan +veil +vein +venom +vent +venue +verb +verge +vest +vet +vial +vibe +vibes +vice +video +view +vigil +vine +vinyl +viola +viper +virgo +virus +visit +visor +vista +vocal +vodka +vogue +voice +void +volt +vote +voter +vow +vowel +wacko +wad +wade +wader +wads +wafer +waft +wag +wage +wager +wages +wagon +wail +wain +waist +wait +wake +walk +wall +waltz +wane +want +war +ward +ware +warp +wart +wash +wasp +waste +watch +water +watt +watts +wave +waver +wax +way +ways +wear +weave +web +wed +wedge +week +weird +well +wells +welsh +west +wet +whack +whale +wharf +wheat +wheel +whey +whiff +while +whim +whip +whirl +whisk +white +who +whole +whore +why +wick +widow +width +wife +wig +wild +will +wilt +wimp +win +wince +winch +wind +wine +wing +wings +wink +wipe +wiper +wire +wise +wish +wit +witch +wits +woe +wolf +woman +womb +won +wood +woods +woof +wool +word +words +work +works +world +worm +worry +worse +worst +wort +worth +wound +wow +wrack +wrap +wrath +wreck +wring +wrist +wrong +yam +yard +yarn +yawn +yay +year +years +yeast +yell +yes +yeti +yield +yoga +yolk +young +youth +zap +zebra +zinc +zing +zip +zit +zone +zoo +zoom +zero +zany +whir +welt +whig +wand +twin +tribe +tilt +sword +spine +spear +site +shock +sent diff --git a/src/auth/src/plugins/words.ts b/src/auth/src/plugins/words.ts new file mode 100644 index 0000000..e1fd6fc --- /dev/null +++ b/src/auth/src/plugins/words.ts @@ -0,0 +1,40 @@ +// Why does this file exists ? +// We want to make random-ish username for the guest, but still reconizable usernames +// So we do `${adjective}_${nouns}` +// there is around 30k combinaison, so we should be fine :) + +import fp from 'fastify-plugin'; + +// @ts-expect-error: Ts can't load raw txt files - vite does it +import _adjectives from './files/adjectives.txt?raw'; +// @ts-expect-error: Ts can't load raw txt files - vite does it +import _nouns from './files/nouns.txt?raw'; + + +type WordsCategory = 'adjectives' | 'nouns'; +type Words = { [k in WordsCategory]: string[] }; + +function toTitleCase(str: string) { + return str.replace( + /\w\S*/g, + text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase(), + ); +} + +// strong typing those import :) +const RAW_WORDS: { [k in WordsCategory]: string } = { adjectives: _adjectives, nouns: _nouns }; +const WORDS: Words = Object.fromEntries(Object.entries(RAW_WORDS).map(([k, v]) => { + const words = v.split('\n').map(s => s.trim()).filter(s => !(s.startsWith('#') || s.length === 0)).map(toTitleCase); + return [k, words]; +})) as Words; + +export default fp(async (fastify) => { + fastify.decorate('words', WORDS); +}); + +// When using .decorate you have to specify added properties for Typescript +declare module 'fastify' { + export interface FastifyInstance { + words: Words; + } +} diff --git a/src/auth/src/routes/guestLogin.ts b/src/auth/src/routes/guestLogin.ts new file mode 100644 index 0000000..713d032 --- /dev/null +++ b/src/auth/src/routes/guestLogin.ts @@ -0,0 +1,54 @@ +import { FastifyPluginAsync } from 'fastify'; + +import { Static, Type } from '@sinclair/typebox'; +import { typeResponse, makeResponse, isNullish } from '@shared/utils'; + +export const GuestLoginRes = Type.Union([ + typeResponse('failed', 'login.failed.generic'), + typeResponse('success', 'login.success', { + token: Type.String({ + description: 'JWT that represent a logged in user', + }), + }), +]); + +export type GuestLoginRes = Static; + +const getRandomFromList = (list: string[]): string => { + return list[Math.floor(Math.random() * list.length)]; +}; + +const route: FastifyPluginAsync = async (fastify, _opts): Promise => { + void _opts; + fastify.post( + '/api/auth/guest', + { schema: { response: { '2xx': GuestLoginRes } } }, + async function(req, res) { + void req; + void res; + try { + const adjective = getRandomFromList(fastify.words.adjectives); + const noun = getRandomFromList(fastify.words.nouns); + + const user = await this.db.createUser( + `${adjective} ${noun}`, + // no password + undefined, + // is a guest + true, + ); + if (isNullish(user)) { + return makeResponse('failed', 'login.failed.generic'); + } + return makeResponse('success', 'login.success', { + token: this.signJwt('auth', user.id), + }); + } + catch { + return makeResponse('failed', 'login.failed.generic'); + } + }, + ); +}; + +export default route; diff --git a/src/auth/src/routes/otp.ts b/src/auth/src/routes/otp.ts index d555eeb..0a690aa 100644 --- a/src/auth/src/routes/otp.ts +++ b/src/auth/src/routes/otp.ts @@ -44,7 +44,7 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise => { } // get the Otp sercret from the db - const user = this.db.getUserFromName(dJwt.who); + const user = this.db.getUser(dJwt.who); if (isNullish(user?.otp)) { // oops, either no user, or user without otpSecret // fuck off diff --git a/src/auth/src/routes/whoami.ts b/src/auth/src/routes/whoami.ts deleted file mode 100644 index 13232b6..0000000 --- a/src/auth/src/routes/whoami.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { FastifyPluginAsync } from 'fastify'; - -import { Static, Type } from '@sinclair/typebox'; -import { isNullish, makeResponse, typeResponse } from '@shared/utils'; - - -export const WhoAmIRes = Type.Union([ - typeResponse('success', 'whoami.success', { name: Type.String() }), - typeResponse('failure', 'whoami.failure.generic'), -]); - -export type WhoAmIRes = Static; - -const route: FastifyPluginAsync = async (fastify, _opts): Promise => { - void _opts; - fastify.get( - '/api/auth/whoami', - { schema: { response: { '2xx': WhoAmIRes } }, config: { requireAuth: true } }, - async function(req, _res) { - void _res; - if (isNullish(req.authUser)) {return makeResponse('failure', 'whoami.failure.generic');} - return makeResponse('success', 'whoami.success', { name: req.authUser.name }); - }, - ); -}; - -export default route; diff --git a/src/package.json b/src/package.json index 2f2f44c..40279f1 100644 --- a/src/package.json +++ b/src/package.json @@ -6,6 +6,7 @@ "workspaces": [ "./@shared", "./icons", + "./user", "./auth" ], "lint-staged": { diff --git a/src/user/.dockerignore b/src/user/.dockerignore new file mode 100644 index 0000000..c925c21 --- /dev/null +++ b/src/user/.dockerignore @@ -0,0 +1,2 @@ +/dist +/node_modules diff --git a/src/user/entrypoint.sh b/src/user/entrypoint.sh new file mode 100644 index 0000000..2dcab02 --- /dev/null +++ b/src/user/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e +set -x +# do anything here + +# run the CMD [ ... ] from the dockerfile +exec "$@" diff --git a/src/user/extra/.gitkeep b/src/user/extra/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/user/package.json b/src/user/package.json new file mode 100644 index 0000000..334414c --- /dev/null +++ b/src/user/package.json @@ -0,0 +1,36 @@ +{ + "type": "module", + "private": false, + "name": "user", + "version": "1.0.0", + "description": "This project was bootstrapped with Fastify-CLI.", + "main": "app.ts", + "directories": { + "test": "test" + }, + "scripts": { + "start": "npm run build && node dist/run.js", + "build": "vite build", + "build:prod": "vite build --outDir=/dist --minify=true --sourcemap=false" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@fastify/autoload": "^6.3.1", + "@fastify/formbody": "^8.0.2", + "@fastify/multipart": "^9.0.3", + "@fastify/sensible": "^6.0.0", + "@fastify/static": "^8.2.0", + "@sinclair/typebox": "^0.34.40", + "fastify": "^5.0.0", + "fastify-cli": "^7.4.0", + "fastify-plugin": "^5.0.0" + }, + "devDependencies": { + "@types/node": "^22.1.0", + "rollup-plugin-node-externals": "^8.0.1", + "vite": "^7.0.6", + "vite-tsconfig-paths": "^5.1.4" + } +} diff --git a/src/user/src/app.ts b/src/user/src/app.ts new file mode 100644 index 0000000..e9156e7 --- /dev/null +++ b/src/user/src/app.ts @@ -0,0 +1,38 @@ +import { FastifyPluginAsync } from 'fastify'; +import fastifyFormBody from '@fastify/formbody'; +import fastifyMultipart from '@fastify/multipart'; +import * as db from '@shared/database'; +import * as auth from '@shared/auth'; + +// @ts-expect-error: import.meta.glob is a vite thing. Typescript doesn't know this... +const plugins = import.meta.glob('./plugins/**/*.ts', { eager: true }); +// @ts-expect-error: import.meta.glob is a vite thing. Typescript doesn't know this... +const routes = import.meta.glob('./routes/**/*.ts', { eager: true }); + +// When using .decorate you have to specify added properties for Typescript +declare module 'fastify' { + export interface FastifyInstance { + image_store: string; + } +} + +const app: FastifyPluginAsync = async (fastify, opts): Promise => { + void opts; + await fastify.register(db.useDatabase as FastifyPluginAsync, {}); + await fastify.register(auth.jwtPlugin as FastifyPluginAsync, {}); + await fastify.register(auth.authPlugin as FastifyPluginAsync, {}); + + // Place here your custom code! + for (const plugin of Object.values(plugins)) { + void fastify.register(plugin as FastifyPluginAsync, {}); + } + for (const route of Object.values(routes)) { + void fastify.register(route as FastifyPluginAsync, {}); + } + + void fastify.register(fastifyFormBody, {}); + void fastify.register(fastifyMultipart, {}); +}; + +export default app; +export { app }; diff --git a/src/user/src/plugins/README.md b/src/user/src/plugins/README.md new file mode 100644 index 0000000..1e61ee5 --- /dev/null +++ b/src/user/src/plugins/README.md @@ -0,0 +1,16 @@ +# Plugins Folder + +Plugins define behavior that is common to all the routes in your +application. Authentication, caching, templates, and all the other cross +cutting concerns should be handled by plugins placed in this folder. + +Files in this folder are typically defined through the +[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module, +making them non-encapsulated. They can define decorators and set hooks +that will then be used in the rest of your application. + +Check out: + +* [The hitchhiker's guide to plugins](https://fastify.dev/docs/latest/Guides/Plugins-Guide/) +* [Fastify decorators](https://fastify.dev/docs/latest/Reference/Decorators/). +* [Fastify lifecycle](https://fastify.dev/docs/latest/Reference/Lifecycle/). diff --git a/src/user/src/plugins/sensible.ts b/src/user/src/plugins/sensible.ts new file mode 100644 index 0000000..8c2093c --- /dev/null +++ b/src/user/src/plugins/sensible.ts @@ -0,0 +1,11 @@ +import fp from 'fastify-plugin'; +import sensible, { FastifySensibleOptions } from '@fastify/sensible'; + +/** + * This plugins adds some utilities to handle http errors + * + * @see https://github.com/fastify/fastify-sensible + */ +export default fp(async (fastify) => { + fastify.register(sensible); +}); diff --git a/src/user/src/routes/info.ts b/src/user/src/routes/info.ts new file mode 100644 index 0000000..a9ba71f --- /dev/null +++ b/src/user/src/routes/info.ts @@ -0,0 +1,56 @@ +import { FastifyPluginAsync } from 'fastify'; + +import { Static, Type } from '@sinclair/typebox'; +import { isNullish, makeResponse, typeResponse } from '@shared/utils'; + + +export const UserInfoRes = Type.Union([ + typeResponse('success', 'userinfo.success', { name: Type.String(), id: Type.String(), guest: Type.Boolean() }), + typeResponse('failure', ['userinfo.failure.generic', 'userinfo.failure.unknownUser', 'userinfo.failure.notLoggedIn']), +]); + +export type UserInfoRes = Static; + +const route: FastifyPluginAsync = async (fastify, _opts): Promise => { + void _opts; + fastify.get<{ Params: { user: string } }>( + '/api/user/info/:user', + { schema: { response: { '2xx': UserInfoRes } }, config: { requireAuth: true } }, + async function(req, _res) { + void _res; + if (isNullish(req.authUser)) { return makeResponse('failure', 'userinfo.failure.notLoggedIn'); } + if (isNullish(req.params.user) || req.params.user.length === 0) { + return makeResponse('failure', 'userinfo.failure.unknownUser'); + } + + // if the param is the special value `me`, then just get the id from the currently auth'ed user + if (req.params.user === 'me') { + req.params.user = req.authUser.id; + } + + const user = this.db.getUser(req.params.user); + if (isNullish(user)) { + return makeResponse('failure', 'userinfo.failure.unknownUser'); + } + + + const payload = { + name: user.name, + id: user.id, + // the !! converts a value from to either `true` or `false` + // it uses the same convention from using in a if, meaning that + // ``` + // let val; + // if (something) { val = true; } + // else { val = false; } + // ``` + // is the same as `val = !!something` + guest: !!user.guest, + }; + + return makeResponse('success', 'userinfo.success', payload); + }, + ); +}; + +export default route; diff --git a/src/user/src/run.ts b/src/user/src/run.ts new file mode 100644 index 0000000..d3d410f --- /dev/null +++ b/src/user/src/run.ts @@ -0,0 +1,35 @@ +// this sould only be used by the docker file ! + +import fastify, { FastifyInstance } from 'fastify'; +import app from './app'; + +const start = async () => { + const envToLogger = { + development: { + transport: { + target: 'pino-pretty', + options: { + translateTime: 'HH:MM:ss Z', + ignore: 'pid,hostname', + }, + }, + }, + production: true, + test: false, + }; + + const f: FastifyInstance = fastify({ logger: envToLogger.development }); + process.on('SIGTERM', () => { + f.log.info('Requested to shutdown'); + process.exit(134); + }); + try { + await f.register(app, {}); + await f.listen({ port: 80, host: '0.0.0.0' }); + } + catch (err) { + f.log.error(err); + process.exit(1); + } +}; +start(); diff --git a/src/user/tsconfig.json b/src/user/tsconfig.json new file mode 100644 index 0000000..e6d24e2 --- /dev/null +++ b/src/user/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": {}, + "include": ["src/**/*.ts"] +} diff --git a/src/user/vite.config.js b/src/user/vite.config.js new file mode 100644 index 0000000..aeb8fd8 --- /dev/null +++ b/src/user/vite.config.js @@ -0,0 +1,51 @@ +import { defineConfig } from 'vite'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import nodeExternals from 'rollup-plugin-node-externals'; +import path from 'node:path'; +import fs from 'node:fs'; + +function collectDeps(...pkgJsonPaths) { + const allDeps = new Set(); + for (const pkgPath of pkgJsonPaths) { + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); + for (const dep of Object.keys(pkg.dependencies || {})) { + allDeps.add(dep); + } + for (const peer of Object.keys(pkg.peerDependencies || {})) { + allDeps.add(peer); + } + } + return Array.from(allDeps); +} + +const externals = collectDeps( + './package.json', + '../@shared/package.json', +); + + +export default defineConfig({ + root: __dirname, + // service root + plugins: [tsconfigPaths(), nodeExternals()], + build: { + ssr: true, + outDir: 'dist', + emptyOutDir: true, + lib: { + entry: path.resolve(__dirname, 'src/run.ts'), + // adjust main entry + formats: ['cjs'], + // CommonJS for Node.js + fileName: () => 'index.js', + }, + rollupOptions: { + external: externals, + }, + target: 'node22', + // or whatever Node version you use + sourcemap: true, + minify: false, + // for easier debugging + }, +});