#hangar-dev
1 messages · Page 11 of 1
need suggestions for smth I can append to the version string to make it unique per-project
have it be only the rowid in the db?
but I think it's nice to have the version string somewhere in the url
hangar.papermc.io/Machine_Maker/EpicPlugin/versions/1.3.2.302
hangar.papermc.io/Machine_Maker/EpicPlugin/versions/<version>/<db-row> ?
<db-row>/<version> would be better ig. 1.3.2.302 technically matches how spigot does it
maybe that doesn't make sense if you're supporting multiple platforms tho
well, xenforo
yeah, its possible the best thing, would be make the version string and the platform be unique, and then put the platform in the url.
would be complex, cause you can have 1 jar that supports all 3 platforms
mega jar 😡
thicc jar*
über jär

I don't like the idea of manipulating the user version by adding an id they can't control, that seems meh
well the correct version is the one displayed most places
except the url, cause there needs to be smth there that's unique
If our only usecase for same version different jar is multiple platforms. We could throw that into the url?
yes, that's what spawned the need for projects to have versions w/the same version string
throw what into the url?
Ideal
Or /versions/1.2.3-paper
Or paper-1.2.3
Then we also have an easy primary key in the DB
Which acts as an index
well... a version can have multiple platforms. Right now, the platform (along with what versions of that platform) are stored in a JSONB column in project_versions
that should probably be refactored into a separate db table
platform_dependencies
- id
- platform: string
- versions: string array
then on project_versions, you'd have
- platforms: id array (linked to platform_dependencies.id)
how would you do a unique constraint on that?
Yeah i never liked the json in the table
Oh right the version has the platform as a normal dependency
Mmh
no, its a separate dependency
one to keep track of what platform versions its compatible with, and one to keep track of what other plugin dependencies are needed for each compatible platform
mini, you got a problem w/wiping the staging db for this too? cause I don't really want to write an sql migration to convert JSONB into the new db rows
yeah
ok, so I think this is probably good?
https://paste.gg/p/Machine_Maker/6052cf57746f40d08509ae356654ac4e
Yep
some projects are gonna add like 40 rows combined to those tables
like, 1.8-1.16 is 8, same for waterfall, 8, 2 for velocity, so that's 18 just for platform
idk, I like the checkbox array better, maybe cause it matches spigot?
if we didn't want to link it to the platform_versions table (thats the table that admins use to add new versions for each platform), we could cut down on stuff by just storing a string array of the versions
but then it wouldn't update automatically if an admin deleted a platform version (idk if that would ever happen)
Mmh
Guess min max because impossible quickly if you wanna say support only versions ppl use, like latest and 1.12, but nothing in between
So yeah rows are cheap anyways
yeah, I don't really know how much space database stuff takes up, but its not storing much, just a few numbers and a timestamp
@pallid yoke do you recall what the jobs db table was for? and do we need to keep it around?
jobs was there to match Ore's tables I think
iirc Ore uses it for queueing up forum post tasks? idk
well I won't get rid of it unless we know we don't need it then.
We don't about forum shit yet so we don't know if we need it
ugh... why doesnt BindBean know isLocked is the equivalent of getIsLocked for a boolean field...
iirc get/set prefixes are mandatory for beans
yeah, looks like this is the thing
@hidden marsh here
Any 1.16 vault economy plugin?
Wrong channel...
were ca I ask?
nuked my local DB, now I got no projects to test again
guess am doing UI for the project creator 😂
mmmh
auth doesnt work for me
seems I dont get the returnRoute cookie
(fake user)
console.log("set cookie " + redirect)
$cookies.set('returnRoute', redirect, {
path: '/',
maxAge: 120,
secure: true,
});
console.log("get " + $cookies.get("returnRoute"))
set cookie /
get undefined
cool cool
I had the same issue at work yesterday and rage quitted
urg
it works in console (document.cookie works, which is what the lib is doing) but it doesnt in code?
removing secure did the job
who you talking to bro
its called async conversation, when jake wakes up he will understand why I did what I did
looks pretty nice, only thing I don't like is that you have to scroll down and it then scrolls up again
(also I personally prefer having everything on one page but ¯_(ツ)_/¯)
also why no "import from github readme/releases" :S
well its one page, but allows you to quickly skip steps
that page currently doesnt allow you to enter the project description really, thats you do on the project page
but its the sanest way to add the spigot bb code converter
and yes the scroll behavior seems a bit wonky
There might be an event you can listen to to have it scroll to the right spot?
Huh... I added the secure so Firefox would quit sending me a warning saying it’s not secure. But it worked for me 🤷 might be a browser difference there
I was surprised that it worked for me, cause I thought secure meant it required https which isn’t a thing on localhost
firefox might just ignore it on localhost
I’d just change it to a horizontal stepper then.
(If you can’t figure out the scrolling stuff)
I haven't looked at it
And yes, normally browsers ignore secure on localhost and still accept the cookie
Felt that though
Oof 😅 I'm not one to open github issues cause I forget but still felt
Oh boi 😅
I'd look through them and see what I could help with but I've got 2 large projects already 😅
only two? pffff
Well, the AntiMalware project is one. I need to finish it's db... Whitelist a bunch of stuff then blacklist a bunch of leaked shit
Then I got bored, said fuck it. And now I'm also merging it into a fork of paper cause I rembered someone bringing the idea up in DMs
Better integration
how is it better?
Instead of a bunch of transformers and reflection it's added directly to the jar. Also deals with the issue of not being able to run the jar on certain hosts, while not making it incredibly easy to remove
why not a plugin? seems easier to update and stuff
well, it seems more accessible that way tho
more likely someone will create a bypass though as well
nobody is going to install a dum server fork just for this
Yea ik, i got nothing better to do 🤣
internet's shit atm as well, so I'm kinda limited in what i can DL and stuff 😅
Ping ms
20
Download Mbps
2.62
Upload Mbps
0.18
peak 153 KB/s 👌
I'm pretty much treating the fork as a POC more than anything really, it'll be dropped once either finished or I get better internet 🤣
@random badger just saw this, https://i.imgur.com/w2N5soV.png, so chrome is really blocking secure cookies on localhost:3000
That’s annoying. I guess set them to secure if not development
yeah or I get a reverse proxy for localhost
or set webpack to do https I guess
idk, doesnt matter for me too much rn as I dont do much auth stuff but ill deal with that eventually
added swagger
this is fine
I cant figure out where the swagger css is
lol
oh, its in the vue
u woot
hmm, maybe it doesn't like the "scoped" part?
is it still in "scoped"?
but it doesnt need to
the html it generates won't have the data-v-aosdhnlfahjsdf
does the data-v need to be added to every element?
yeah, that's how the scoped works
look at the page source and you'll see that on a bunch of stuff
like, scoped css won't apply to stuff in a child component
also, I see you added a bunch of en locale stuff for the project create stepper. should some of those be reused? or should everything have a separate entry? Like the Issue Tracker, Source Code, that stuff is used elsewhere, in project settings, and in the project page tabs
yeah I thought about that
idk, we can prolly in the end merge stuff together
swagger looks really ugly now but I dont really care for now, we can write a dark theme for that later, lol
someone has to have done a dark theme for swagger already... but yeah
re: editiable stuff, I saw that vuetify has a full crud editor, that is most likely perfect for this https://vuetifyjs.com/en/components/data-tables/#crud-actions
or do we wanna have a "nice" ui for those?
nah, cause its just admin stuff right?
I saw the platform versions thingy, thats nicer than just crud
idk, I dont really mind tbh
re: swagger themes https://ostranme.github.io/swagger-ui-themes/
A collection of themes to spice up your Swagger Docs
they all ugleh 😄
this is nice
oh yeah, I like that
much more material-y
is it maintained?
last commit was over 2.5 years ago
idk it doesnt seem to be designed as a lib
oh, its like a standalone api explorer thing
idk we got bigger issues
having treeShake false makes vuetify ignore customVariables
the mapping to user doesnt work
as the ctor needs more entries
in old we had author and staff models
does the /staff and /authors have to be public api? we could just replicate the author/staff models for internal use
it just doesn't seem like that needs to be part of v1
I dont really care, they need to be accessible
I am slowly loosing the overview over the backend 😛
is it too confusing? I was trying to make it simpler to understand in the end w/stuff in more seperate packages
like you have API controllers, and internal controllers (ones that only are used via nuxt)
for DAOs you have "common" ones, ones for internal models, and ones for api models.
instead of having one package that has like 25 dao interfaces
yeah, its nice
I just yesterday discovered the purpose of row reducers for daos, and realized we should be using them in more places probably
the more I use jdbi, the more I like it, it really seems to have everything
I really need to do a deep dive into jdbi, lol
actually, I think the api User model has everything for the staff page
it has a list of global roles, which can just be sorted on the frontend to get the "top" one
it has everything but requires more than that query returns
which is why jdbi is complaining
oh I see what you mean
I thought you meant it required more than the User model had
yeah I see that bit. can probably just add that to the Api user model tbh
OOP was a mistake, lets just send nested maps
? for everything?
it was a joke, lol
or is that a joke? or smth
oh ok, I thought it might be, but I wasnt sure...
idk 😆
JS hasnt made me that insane yet 😛
am gone for today now, merging one or two PRs and then a friend is coming over
oh also quick note mini, we switched to using ConstructorMappers for sql queries, so use @RegisterConstructorMapper(User.class) instead of @RegisterBeanMapper
just makes the Model objects nicer to deal with I think
Ah ok
when inserting, sill use @BindBean cause it just needs the getter methods
@pallid yoke so how does spring store its user sessions? just in memory? that doesn't seem ideal
cause I've noticed if I re-build the project, I get logged out, which doesn't seem like it should
in memory by default
I think
These days, really, just use JWT
🤷♂️
Outside of JWT, you'd just do the good ol' slap it in a database
yeah, idk how to set that up w/spring
mm hmm, reading up on this https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
we are doing our API authentication almost manually, probably should switch to smth like this
so with JWT, you don't need to store anything on the backend because it "encodes" the user into the token itself
for stuff like actual APIs, JWT is basically the standard these days afaik, as you don't need to store a token on the server which deals with that aspect, and supports expirery, etc
worse case is that you basically need to store something somewhere if you wanna revoke older tokens, e.g. set the min issue time
Well ideally, the spring backend for hangar is moving entirely to a api, rather than it serving the pages itself. So I like the idea of JWT. Not sure how that all works with hangar since the real authentication is done by HangarAuth.
Hmm except we need to use cookies here. Cause nuxt does the initial page render server-side, which doesn’t have access to the client’s local storage (where you’d store the token)
You don't have to use cookies
It's more just the scheme
For browsers, you'd generally use a cookie given thats the only server accessible thing
For json apis, you'd generally use the auth header or put it in the request itself
Ok mini, here's what I'm thinking. The public API should be changed to follow the JWT spec and the authentication can be done pretty similar to how its done here https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
As for the user side of things, I'm still not sure because we want it to be cookie-based so the server has access to it for server-side rendering
for the user side, we still generally just use JWT
You're still essentially authing to the backend API, so it makes sense to just share a token between the two rather than getting the front end to essentially double-auth or something
Why did you add this back? I removed it because I thought I don't need it since it's in the options
Ah yeah, that was left over from when I was testing smth. Should’ve been removed
smh smh
And yes, by default session is just in memory, but i you can do all kind of funky stuff to persist it. At work session is replicated in the whole cluster for example
But yes i don't mind going full jwt
Also makes the whole permission api unnessasary as we would encode the roles and perms in the token
Yeah, that sounds fine. But I’m still not understanding how you do JWT with server side rendering? You don’t have the client’s token.
I thought JWT was supposed to be a header
So as to not be vulnerable to csrf stuff
Oh ok. I didn’t see any examples in my googling around that showed it elsewhere. I just assumed there was a standard.
with websites, you don't really have the ability to control it, you either keep your sessions stateful on the server, which ofc doesn't scale, or, you just give the client some means to pass a token back
cookies are basically the only real sane storage mechanisms that the web browser offers which doesn't basically involve js on the client side to pass in the auth header, etc
Well... not entirely, cause it doesn’t have the scoped permissions, for projects, etc. just global ones
🍪
Right
And we can just accept the token however
We can have a filter for auth that just searches an request param, the cookie and the header
Well, that’s kinda what the Voters do now right? To check if the user has a permission
In some examples I found online, they turned off HttpSession creation for spring, by setting smth to STATELESS, would we want to do the same? If it’s all the token, does the server need to create those?
depends on if you wanna use spring session states in there
if you're not using anything which depends on spring creating sessions, no reason it needs to create them
I would have one thing reading the token from wherever and storing it as a request attribute
And then one thing to do auth based off of that
And then the access decision voters can do their thing
I can look at stuff in a few, got like 1:30 time till I go to my parents
Why the two separate steps? Can’t one filter that extends AbstractAuthenticationProcessingFilter get the token and create the Authentication?
Sure, whatever
It's just two logical steps, so i automatically try to extract them
But just using methods makes sense too
should I implement jwt auth now or do you wanna do it @random badger ?
Nah, if you want to go ahead. I’ll look at it in the morning.
How does expiring work w/JWT? Is it like oauth, where you have a refresh token, or what?
You'd just basically store a minimum issue time
There's no real sane way to do it without basically storing something somewhere locally you can use to validate if they're still valid, otherwise it purely just relies on you setting an expiry time
mmh I am not sure how refresh tokens would work
This looks like an impl of one, (in JavaScript, but concepts should be similar) https://valor-software.com/articles/json-web-token-authorization-with-access-and-refresh-tokens-in-angular-application-with-node-js-server.html
That’s the initial attempt?
oh, I was confused on what you meant by refresh, thought that you meant like changing password "get rid of all the old sessions" type stuff
Well... you bring up an interesting point, how can the server “invalidate” a JWT
what I said, server just stores a min issue time
if the token was issued before then, consider it invalid
with JWT, you'd store the issue time in the token
Change the minimum issue time so it's after when the token got issued
then on the server, if the minimum issue time is after when the tokens issue time was set, it's expired
I’m still not understanding smth,
Say I have a token that lasts for 15 minutes, after which, server will say it’s invalid. But I change my password in 3 minutes, that token is still gonna be valid for 12 more minutes.
Yes, but the server is in control of reading that token
the server can read when the token was issued
You'd just treat the token as if it was already expired
Yeah, the server (in this case) doesn’t know the password was changed, since that’s separate.
We’d need to do smth with sync_sso to tell hangar to invalidate tokens
the server would have to validate the token against the API if you wanted stuff like token expirery
ill be lazy and just use a secret for tokens
as we dont need ppl to validate tokens really
as the server does validation
didnt get anywhere, pushed my progress
Could make sync_sso always invalidate tokens
That way, you always reissue tokens when the user roles/pw changes, and then Hangar leaves it up to hangarauth whether the user stays authed to has to log in again
I forget how often that’s called. If it’s only on hangar auth user table updates user
Wait @pallid yoke I just see that you created a new branch, but no new commits on it?
kek
shhhhh
It's my job
also mini, I think we do need to have two separate authentication systems, one for the frontend, and one for the public API, since that has the whole api key system to deal with
I'm talking about the api keys that the user creates, and specifies what permissions the key has
it'll be via a jwt, but that's separate from actual frontend user authentication, or it should be I think
unless we want to just scrap the whole existing api key system, and just have the user specify what perms they want, and give them a jwt for that
instead of having the jwt kind of act like a wrapper for the api key
So
a user logs in, gets a JWT with their current global permissions, user id, etc.
a user creates their own "api key" for whatever external use they want, they get a JWT with their requested permissions (assuming their user has them in the first place), their user id, etc.
then we have the unauthenticated public api, where you currently just create a public session, how do we want to handle that jwt-wise?
anonymous auth should allow stufff where you dont need perms I guess
do we just not want to require a jwt for that stuff then?
there is no real need i guess
I wasn't sure what the point of getting apublic session was in the first place?
🤷
well the whole API key thing does still make sense, since those never expire, you use your api key token to get a JWT, and use that to make api requests
I still think that calls for separate auth providers since one is dealing with api keys, and one isn't
yeah I guess
So are you planning to use JWT for api authentication? JWT's are not meant to be used for API authentication since revoking them is difficult and they are only mean't to be have short lifetimes
Well nothing is for sure there. I don’t know very much about auth schemes so I’m learning as I go. For the public api, the plan was for users to generate their own API keys to take advantage of their permissions, or have no api key for all public stuff. Then you use or api key (or not) and that gives you a JWT that has a limited lifespan, aka not long
Do you have another suggestion? @gusty birch
The only time I have done API keys was in a fastify app. Basically I have a api_key field on the user object in mongo. Then had a auth provider for api_key routes.
I had a getUserApi(key) function which got the user via their api key and then attached there roles to the request with the auth middleware
hangar has a system where a user can create an unlimited amount of api keys, each with different permissions based on the users possible permissions
Making the user get a JWT with there api key just adds more logic to there app a scripts that are hitting the api
Ah so its not 1 api key rules them all. So you have a key that can read or edit certain things
yes
Ore (sponge's plugin repository) had users use their api key, to get a session which was then stored in a db table and valid for a limited time. when that ran out, they had to use their key again to get a new session
if they didnt have a key, or want to use one, they could get a public session token and use that for api requests
I think the goal of JWT was to not have to bother with storing anything in a database for user sessions
So permissions for the api are like EDIT_PLUGIN etc?
yeah essentially. https://paste.gg/p/Machine_Maker/e4380fba91664772b4c86957a9b93ffb
stuff like that
Using JWT's and making the user get a new sessions kinda defeats the purpose of having a API key or atleast adds another level of complexity to it
Maybe something like a table of api keys with the user id and the permissions associated with it
so you think just using the api key itself for requests is better
yeah we already have that, cause the api keys have to be stored somewhere
Yeah I would think something like USERID | KEY | PERMS
Like how the user permissions are stored with spring
My example with mongo has a array roles field on the user document
So with the api key it would just be a permissions array
One thing this reminds me of is gitlabs access tokens. And them defining scopes for the tokens
Mini, I can’t figure out how to get the filter to work. I turned on TRACE level logging, and it rays it can’t find an authentication provider for the Anonymous token... I messed around w it for a while.
I think the HangarAuthFilter should return null, and let the anonymous auth filter return the anonymous auth token, but I can't seem to get that to work
yikes, ok got it finally
Consulted on of my artists and we will have a new logo in the works starting tomorrow
nice
Idk Mini, so I got the user auth working, I’ll push what I’ve got to the JWT branch, but I’m not longer convinced that’s the way to go. The whole “no invalidation” thing is kinda eh to me. Like most places suggest you really should limit them to 5 minutes or smth, and then what’s the point in the first place? Curious what you think as well since I’m not an authority on this stuff. We def still should use the spring auth filter/provider/token system, that’s great and I’ve learned a ton about it from just trying to get this to work, but idk if JWT is the way to go.
Whatever we decide, it does need to change from what we had before, I just am not sure what scheme we should move to
I did however just find this article https://supertokens.io/blog/are-you-using-jwts-for-user-sessions-in-the-correct-way
and what I implemented is pretty similar to that, (just have to decrease the expiry of the jwt)
Yeah a refresh token is the way to good
But that means that the api keys for users are also just refresh tokens?
I guess, in a sense.
Maybe we could do some sort of non-opaque refresh token that limited permissions. That way the same auth scheme could be used for both api and user?
That might be redundant, cause you’d still query the perms anyway to make sure they still had them
Ok, let's make api keys work like refresh tokens, but they don't look in the session table but in the api key table, where the perms are
If we can make the format for api keys and refresh tokens slightly different, we can automatically detect what to check
Ok, then I think we’d still want separate filter/provider for the api keys. And you could just match against the request route there
I don't think so
As auth is always jwt
And if your jwt is no longer valid you call /auth/refresh with your refresh token/api key and get a new jwt
And only that refresh controller needs to know about how to validate the two different types
Hmm yeah ok.
And normal api can enjoy the database and stateless validation of the jwts
Tmrw I can try to finish up auth, and then we can get back to other stuff
Hopefully I can continue on UI later after work
My free time is so unreliable lately, lol
I’ve been trying to NOT do marathon sessions on hangar cause I’ve gotten totally burnt out before. Happened yesterday trying to figure out wtf was wrong with the auth. Got pretty frustrat
Yeah i know that
Hopefully the UI layout stuff gets faster the more experience i have with vuetify
So how are the tokens supposed to work?
You generate refresh token through webui, then app generates token and uses it until it expires, at which point it should use the refresh token again?
And refresh tokens don't expire?
So, I can ditch saving the JWT api token, and each time first use refresh token to create new api token?
Wait so for the API you will it as JWT auth? You login get a access token and refresh token?
Using JWT for the api seems like a bad idea. Revoking those keys seems like it will add alot of extra work then just using scoped keys
Say if my refresh token leaked. Its hard to easily revoke that key without added logic to the API auth provider. Which then seems to defeat the purpose of using a JWT
JWT's are great for SPA apps. Where you supply the refresh code. Having to making users of the API setup a oauth flow in there API app just seems redundent
By adding a type claim there.
claims put("type", "API");
and
claims.put("type", "human");
Parsing the claims and depending on the type, look into the HumanTokenVeryfier or ApiTokenVeryfier
Refresh token can expire after 30 days for example.
That wasn't my point, but I do hope refresh tokens can be made expirable by user, if needed.
The only way a refresh token (JWT) can be revoked is with a blacklist on the server side
Or embedding a value in the token say version: 1
And then incrementing it when say a users changes there password
Just, if I understand correctly:
I create token with permissions, which won't expire.
My app then auth uses this token to generate short-lived JWT.
Uses this token throughout its life (assuming its short-enough).
Doesn't save it and next app run repeats it.
Refreshing requires DB lookup, to make sure that token wasn't revoked.
Using generated token in API doesn't need lookups.
Basically from the sounds of it yes
But you would still need to check if the token generated with the refresh token hasn't been revoked
Even if its 5 minutes lifetime that stills leaves time where the token is active if leaked
The whole process is described here
Looking at this file https://paste.gg/p/Machine_Maker/e4380fba91664772b4c86957a9b93ffb and all the permissions you can give a api_key not being able to immediately revoke them seems like a problem
This is a great article saying when to use JWT's https://developer.okta.com/blog/2017/08/17/why-jwts-suck-as-session-tokens
Learn why you should never use JSON web tokens as session tokens (either in cookies or HTML local storage).
For the website auth browser to server. I think JWT's are fine to use. But for apps like python scripts etc they are not a good solution
I didn't say that we would use jwt as a refresh token
We can use whatever format we want for that
The refresh token is a proper session token
But it's only ever used to get access token if we wanna stay in oauth speech, which is a jwt
All apis require that access token jwt
Well, not true, we will support Anonymous access where it makes sense
e.g. the user login call. 📞
But also a bunch of the internal api
Like, you should be able to view the home page without logging in ^^
It's just that you potentially see more if you log in
Man, now I’m more confused on what the plan is.
(For the api)
I don’t think the whole “revoking JWT” is an issue with the user stuff cause we still check if the user still has perms for an endpoint that requires them.
then JWTs are usless 😄
the point is to not do the DB lookup
lemme try to explain
all requests require an JWT (or are treated as anonymous, some request might be ok for accessing without logging in, only internal ones tho, all api requires a token)
you can get those JWTs by authenticating either via username+password or using a refresh token or using a api key
JWTs are valid for 5 min
refresh tokens are valid for longer, don't have any perms attached to them, its just "owner of this token is allowed to get a jwt for this user"
they are stored in the DB, they are basically "sessions", one session per device basically, but multiple sessions per user are possible
they are basically the only state we have
Ok, then I think the HangarUser model is the wrong thing to provide via the hangar auth provider, since that does a db lookup for a bunch of information
need a separate model that just has name, id, and a binary string of global permissions or smth
that way, in the Hangar auth provider, you don't need to do any db lookups, just parse the jwt into that separate model
I think I understand now
you don't want to do any db lookups relating to the session when using the jwt, only when using the refresh token to issue a new one
ye
But if it doesn't have perms, I have to basically give FULL access to my account to such token? Can't only give RO access to resources.
I have no idea exactly what kind of data will be exposed.
well if we use api keys AS refresh tokens, they will have permissions attached to them.
I think mini was talking about the session-tracking system. Those refresh tokens are just a string attached to a user
yeah, we basically have both "full access" refresh tokens and limited refresh tokens (aka api keys)
and I guess the limited refresh tokens (aka api keys) have an unlimited life, until the user the created them deletes them
yeah
Ah, OK. Nice.
and the user refresh tokens (for the UI) we could limit to 30 days or smth? or also unlimited
but we also allow revoking them in the UI, we would have a "active sessions" thing where you see your devices
(doesnt need to be part of the mvp)
Just wondering howcome for the API you are calling it a refresh token? Wouldn't it just need to be a unlimited life access token?
yeah, that sounds good.
to make the code path easier and to reduce DB lookups
because you use it to "refresh" your jwt that you use to make api requests
if we only ever have one way to access an api, the jwt, that makes the code simpler
I would think caching the API key db request would end up being quicker then jwt
JWTs kinda suck but they are helpful at times
why do they suck?
enough contribution to hangar for today this week
😄
pls
its not going away
lmao
man am not drunk enough for this shit
wtf
1000 IQ https://i.imgur.com/eRr9a8F.png
As long as it compiles, anything will work
how did that happen... its just a div as a root
new feature of hangar
bricks PCs
You know when you wake up in the morning, and by the time you've even picked up your keys you just know, "I really should just go back to bed today before it gets worse"
and yet you leave the house anyways
hey mini, do we want to issue new refresh tokens each time a client calls the refresh endpoint?
or maybe if its within a certain timeframe from expiration?
like within 2 days of its 30 day limit or smth?
I would say update it
that way stuff like "Last Used" is easy to track
and with update I mean delete old and add new
or can you change a primary key?
ON CONFLICT (user_id) DO UPDATE SET created_at = :now, token = :token
idk
I think that is working for me
basically if it tries to add a row with the same user id, it just updates the token
and the created_at
nice
does this mean only one token per user?
because thats not what we want, its one token per device
since the token from my phone and the token from my PC are different
hmm right. yeah, I didn't do that. need some device identifier
what do people use for that?
google does a random ID and then adds OS, IP, Browser, location, date, etc
I swear ive seen applications that have like my PC name in it... maybe those aren't web apps?
ok, so the unique constraint needs to be that identifier
can just do a uuid
I guess we need another unique constraint for the token itself? right now its just a 128 alphanumeric
yeah ok
ok, was about to ask that
I will gladly take that 500, lol
what are the chances anyways
yeah not worth thinking about, but a contraint doesnt cost us anything
and it makes it an index so fast db lookup
just the refresh token right?
we aren't going to be checking the refresh token by itself and the device right? or should we
well I guess I was asking in the future
so it doesnt really matter how we do this, as we will most likely touch it again if we decide to do something like viewing the sessions
which i dont really know how we wanna do that
would most likely be smth like Browser Name - OS - Location
based on user agent and IP
I'm just changing the V1.0.0__init.sql with this stuff, that gonna be an issue for you?
no my DB is empty anyways
ok
I still need to nuke it, but recreating the schema is easy
oh smth I didn't think of, is that we can remove that whole "USER" type of api session, cause we can just say if you are logged in, you have access to the public api endpoints too
no need to generate an api session on the client
also, it seems there is an issue with using html inside localized messages
actually, it seems that came from using v-text on the v-card.
might have to put that on the v-card-text
but regardless, is it fine to using the v-html? it warns of XSS attacks from that, but I'm not sure someone could hijack the localization process
It's the only way to inject html
I think you can make stuff with safehtml, i don't remember
But yeah it's fine these strings come from inside the app bundle
wow, blatent abuse of the system, or something
Mmmh
They don't mention safehtml here
The way we do it is fine, it's not user provided
If we really would care we could do shit like this https://www.npmjs.com/package/vue-safe-html
But it's fine
We never want user generated html, that's why we have markdown (and the markdown parser already handles html)
In all other locations we never want to allow any html, so vues escaping is fine
It's just that sometimes it's convenient to have multi line translations so that why I used v-html in those two cases
generic HELL
can drastically reduce the mess of code for managing users/members or projects/organizations with this, but it needs like 6 generic params
beautiful is it not?
ok mini, so user auth should be done. refresh tokens, getting a new one when expired, etc.
Nice
I'll have a chance look at stuff later
Did you integrate it into the UI already?
Oh mfw am two hours late
Yes I did. Logging in/out should work. But now that you menation it, I didn’t try w/fake user, but it should be fine.
I tried to have the refresh token as an HttpOonly cookie, but I’m not sure that’s feasible
I did just think about smth, mini, do you think if a request is made w/an invalid JWT (expired, malformed, etc.) but a valid refresh token cookie is found, that a filter or smth should generate a new JWT for that request, and send it back to the client in a response header or smth?
We need to respond with 401, else the client will not save the new jwt
Well, can’t it just look if a header is present on the response and save that JWT?
That way, we don’t have to make a request with a bad token, get a response saying it’s bad, then get a new token and re-do the request.
It just condenses that into one request that, at the end, updates the token and new refresh token.
It's not as explicit
And while that works for cookie based authentication, it doesn't work for header based, like some bot or smth
The beauty of jwt is also that you can check the validity yourself
and that still happens
but yeah, I was only thinking about this from a browser perspective
what should the flow be then?
getToken
- if token stored & valid, use that
- if token stored & invalid, fetch new one, no token if that request errors
- if no token stored, fetch new one, no token if that request fails
apiRequest
- if non-null token & 401 (Unauthorized) do what??
- 2xx, proceed
if non-null token & 401 (Unauthorized) do what?? <--- get token 🤷
or well, error out?
try to refresh token and then re-do the api request?
the /auth/refresh or whatever should be the one giving detailed errors
yeah it is.
so like, if you get a 401, you should always try to refresh your token, and if that fails, we will tell you why
the double-api request should rarely happen, since the expiry of the jwt is checked on the client side before making the request.
but if you made the request with a null token, and got 401, I think we can just tell you why right away, because it would have already tried to refresh the token
bascially, if the token is null at the time of api request, you def are not authenticated
so if the request 401s then just show error to the user
well, no token is different, as some apis/internal apis might accept anonymous access
like, the endpoint that lists the projects for the homepage for example
but I think, the external api should always require a token, yeah, and we can yell at you for that in the 401, thats fine
do we merge jwt branch back into frontend refactor branch? its getting confusing, lol
yeah, we can
right, you still make the request if the token is null (because some stuff is anonymous) but if it 401s, you don't have to try and refresh the token, only if it 401s when a non-null token
yeah in our implementation we can just stop then
but realistically, if we try access something (that needs token) without being logged in, thats still a bug in the frontend
yes, I am just thinking its possible if the client thinks the token expiry hasn't passed, but the server does
I think there is a chance that happens
like if a request is made in the instant it expires
normally you add a bit of wiggle there, like plus/minus a few seconds
idk what our jwt lib does
lemme check
yeah, that would totally work then
better to have the client think its expired before it actually is then after
I'll have you know that I really want my token to expire mid request
yeah, client shouldnt send a token that is about to expire, and server should accept a token that just expired
that would be the level of debugging hell I'd adore to unleash upon somebody
10 seconds?
on both ends, have the client check against 10 seconds earlier than the expiry, and have the server allow 10 second late
yeah 10 seconds sounds fine
dont have much time today so I was looking at deployment
but stuff isnt cooperating again
urg
yeah, deploying a site always sucks imo. stuff never just works.
ill do that tomorrow, I can sign off of work early
wanna deploy using gh actions now, no need to do gitlab shit
yeah, good to keep stuff in one place
can finally turn off TRACE logging now... was supremely useful for figuring out the auth stuff in spring, but it just absolutely spams the log
...
Date is not assignable to Date
also, we def need to include the "era" in dates 😆
brb, writing a jesus plugin
just gonna manually set my join date to like 2000 BC
kinda annoyed that the javascript localized date doesn't include the ordinal (st, nd, rd, th)
oh mini, we also want to decide if we want to use the asyncData or fetch hooks for getting page data from the server
well, it actually probably depends. asyncData is only on pages, not components and fetch exposes a useful $fetchState that has some info about what was fetched, and it can be-recalled to refresh the data
if we want to have refresh buttons for information, fetch is the way to go
but idk if we need that everywhere
do acceptLeeway here
that was its in all directions
also for not before and whatever other dates
if fetch works for everything, its nicer I guess
but if asyncData is for pages, thats also used for prefetching and shit, right?
the one downside of using fetch tho, is you have to do v-if="!$fetchState.pending" to ensure its not shown until the fetch is complete (for client-side renders, like when you change page)
like look at notifications.vue
because when the page is navigated to from a client, it doesnt want for fetch to be done before showing the page
which allows for loading bars, etc.
whereas asyncData is
so I think we probably want to use both
only a few places probably need "refresh" functionality
most of the time they can just reload the page
Ok, so asyncdata for pages and fetch for components or exceptions where it's needed
And I mean, we can still call a method in asyncdata if we need refresh
yeah I suppose
Ah fetch can't access component state
I thought it was the other way around
So fetch makes sense if all your data is in a vuex store
cause you can use this in fetch
you can't in asyncData
which is why you have to return an object that gets merged into the component
Oh this answer suggests stuff has changed
I need to read that page, can't rn
ok, time to figure out how to make a custom decorator for doing permissions for pages.
yeah, but it'd be nicer if it was just like @LoggedIn
or @ProjectPermission(MANAGE_MEMBERS) or smth
otherwise its just a bunch of repetitive code
I guess, if it's not too complicated
yeah, we will see
Is that a thing that is a feature?
I see
not like annotations in java, more like decorators in python
if I understand it right
Why doesn't dependabot just... update the pr instead of making a new one if the package has an update
unless it's a config, this is annoying
Doesn't it update PR, unless it get closed?
Wait I thought I changed it to acceptLeeway
Grr. I totally thought I changed it.
Well no, I know I changed it
Idk where the change went
oh thats where the change went
sitting un-pushed
gfdi
Heh, all good, happens to me all the time too
Just left the comment so it doesn't get lost
I'm like dead so am just here to watch y'all burn or something
Like a true cat
so Mini, why did you get this vuetify-preset-reply/rally things? were you just messing about?
it took me a while to realize that it was removing the border-radius on cards
Gonna get the project creation finished up today hopefully. Mini, I kinda re-did some of that page, including rotating the stepper to horizontal, hope that’s not an issue
nah
I saw you suggesting that, tried it, saw I had to redo my html and then didnt bother 😛
I am playing with deployment now
We probably want linting and typescript compilation checks on gh actions too
(Unless either of those make the current check fail already)
yeah I had smth to eat, will continue now
didnt even realize that was a thing
literal trash tier PR
does that cover typescript issues as well? sometimes those don't show up during linting
who'd expect anything less from mini
I would expect those to show up on build jake
better than your non-existent pr cat 🙂
brb, writing a script to see how many branches i can create on a repo
brb rewriting papermc website in coffeescript
I probably wouldn't have it deploy to the existing site just cause we probably are gonna need that for reference. I'm not sure the old frontend will still work locally on nuxt-frontend
and I dont really want to have to run two hangars locally
hangar rebase on bibliothek when
CoffeeScript + AngularJS
yeah am gonna deploy to hangar-new again
"for reasons I don't understand, auth only runs with debug right now. don't question it, unless you want to fix it"
ah yes, forgot about that
runway wen?
shhh
after that we can convert the hangar backend to a graphql endpoint
Ive never used it, I just know a bit about it
using it at work for a project for the first time now
but only as a consumer and only for queries
I made my company use https://directus.io/ for this new project, really ncie tool
oh btw, idk if you have a live template for a new component, but here's one https://paste.gg/p/Machine_Maker/2fff82faa5564577a28a013f761984ba
how woudl I set that up?
search for Live Templates in settings
I just overwrite the vbase one that existed for Vue
but you can add your own in the Vue category
extremely nice, cause I just type vbase and tab and then brand new component all ready
cool
"failed to retrieve context tls info: ca.pem seems invalid"
I think this is where I give up for today
"failed to create service hangar_new_frontend: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: image reference must be provided"
eeeeewwww
seems like I need to build images and then deploy
and upload the images somewhere
github has aregistry now, but that ill do tomorrow
is GitHub's registry as 💩 as its package repo?
or does it let you pull without authenticating
fair I guess
It's not for public consumption so it's good that it's not public
I think i pulled from githubs docker registry before tho without with, idk
I've been looking at that for a personal project. I want to use Elastic and Postgres though and it doesn't seem like it handles multiple data sources very well. Are you using the Node or PHP version?
I use v9, so node
And yes, it's only designed for one data source iirc
If you join their discord, rijk, the lead dev, should be online on might have suggestions for your usecase
Ah yes
ugh... I really want to use the validation annotations for request bodies
but you can't put a spring config value in them afaik
can make our own I guess http://javatar81.blogspot.com/2016/06/hibernate-validator-spring-expression.html
In this article I will describe how to leverage Spring's Expression Language (SpEL) in order to write powerful class-level and cross-parame...
looks so much nicer like this
so for like the new project request body
(those are just the values copied from the .yml configurations)
idk, ore had them, so we did
Yeah sure, it normally makes sense to not hard code them
But if that's making it hard to do stuff, there is no real benefit anymore
well lemme see how annoying custom annotations would be
k, its pretty straightforward
had to figure out how to get the bean resolver into the evaluation context but yeah
ah yes, the ValidateValueMatchValidator. excellent naming
but yeah, I ended up just going w/one annotation that just can be used to evaluate spel expressions
Ah nice
Spring Expression Language is cool.
why are the components suddenly requiring the .vue extension on import statements of other components?
I swear it wasn't doing that yesterday
I didn't touch lint stuff
neither did I 🤷♂️ well it complains if you dont have it. doesnt really matter I guess
well I tried rebasing it onto master and it didn't like that. I guess its not important
force push incoming to there I imagine
It's just behind 2 commits, we can later look at that stuff and then force push
Yeah
Am still required to be at my work PC and debug stuff with ppl, but am slowly waking up now, I'll look at the github Container registry, then we should be able to deploy
oh wait... is that what the pwa module is supposed to do automatically?
I refactored a bit to use the nuxt child component. And... you can create a project. Yay.
Just 400 more pages to go.
wdym with the PWA?
idk what that means :D
did you touch any images or stuff like that?
I did, and then un touched them.
And idk what that means either... I added an “static/icon.png” so the pwa module could do its thing and generate icons
the image is corrupted
Ah now i get it, didn't see your commits, heh
Ok.. so what could be causing the image to get corrupted when I commit/push it?
I’ve never had that happen before
I do get the CRLF will be replaced with LF but IJ still lets me open the image after I get that message.
Strange
Ah good catch on the git attributes
how did you get the file back up there? I assume this wouldve affected you as well
Work pc and github web upload 😂
had a genius idea to tell jackson to ignore serializing certain fields IF the user was missing perms...
owo
Yeah i saw that mapper, that's a nice idea
this bothers me lol
how so?
i can't click where im used to :P
lol
lets see if I can get this to deploy today
urg
backend still uses wrong db
and frontend doesnt want to start
"starting container failed: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "./node_modules/.bin/nuxt-ts": stat ./node_modules/.bin/nuxt-ts: no such file or directory: unknown"
😄
am getting close 😄
I just dont get why my frontend doesnt wanna work
and docker locally isnt cooperating rn
"COPY failed: forbidden path outside the build context: ../docker/deployment/hangar-frontend/entrypoint.sh ()"
oh fuck off
I bet docker is written by britts
it can't read its own configuration file?
cause I didnt add it
Mini is like rescuing every project today.
cracks whip
I dont want large docker images so I only add whats needed
Only coz he breaks every project first
me at work, literally every single day
I am a professional software dumpster fire fighter
he's like that guy who fucks something up for the sole reason of like "look at me, am productive, keep paying me"
😄
woooooo
man this is fast!
lighthouse still got plenty to complain (I think we really wanna selfhost fonts and shit) but this is nice
aslo we added a service worker that doesnt exist?
Yeah everything 90+ except the currently not targeted accessibility.
if my ip is in here... oops http://i.notom3ga.me/VDvQMeWU1y.png
I know about that, will be fixed with next deployment
Wow what's your social security number doing in there?
hangar-auth doesnt work on chrome
even locally
works fine on firefox
been an issue since we started this whole thing
runaway then?
yes, run away indeed
mmmh, what exactly doesnt work for hangar auth?
I was able to login, I get a redirect with a token (to localhost, so I manually add the right host) and then hangar-new redirects me to a url without the token, but am not logged in
token looks valid to me https://i.imgur.com/1xJvS08.png
Oh, I guess I haven’t tried it recently. But I’ve always had problems with hangar auth on chrome.
well, anyways, time to sleep
if you wanna look into why its not logging in, the new mail server url is in my discord
ill hopefully be able to continue doing actual work tomorrow
I think it’s that
Well yes, but even if I fix manually it's not accepting the token when I come back or whatever
Oh, and since I am looking at that cookie thing again that had caused me issues, at work I encode the return route in the jwt
Not sure how applicable that is with our setup, i can't visualize the flow rn, but I find that a nice way to handle it
Yeah, thing is, we don’t send the JWT to the client when they log in, we send the refresh token as a cookie. Then the client uses that when it tries to make an api request.
email verification for hanger-new? or do you guys still have to give it out.
pretty sure they still don't have it as it needs a mail server
ah
Hangar new isnt usable anyways and we will nuke the db often
Not worth it
I got plenty email servers i could use, but we are not in a stage where that's helpful
Helpful would be to help laying out pages using vuetify ^^
sounds like you're just stalling
:P
MONDAY BOIZ
Aww yeah
r0000de
mondays
Well... I think it’s really easy to make something look good with vuetify since all the components already look good. It’s the colors of things that I can never figure out.
Is there a benefit to using webstorm for frontend? I see you have it open sometimes but I don’t really know the actual difference. I always thought IntelliJ could just do everything if you had the plugin.
idk I dont like bloating IJ
and since I own the all products pack, might aswell use it
I was thinking, there are probably a few routes that we can just get rid of. like the api keys management for users, that can probably just be a modal on the user's page
yeah, ok ill do that
need something that returns smth like this
interface Page {
id: number;
createdAt: string;
projectId: number;
name: string;
slug: string;
isDeletable: false;
contents: string;
children: Array<Page>;
}
ok
idk how far you've gotten on the vue components, but I was thinking that a separate component for rendering markdown would be nice because there are quite a few places where all that needs to happen is rendered markdown, no editing
like logs, visibility notices, etc.
yeah gotta split off the editor a bit
I guess it can be recursive
idk how that would work routing wise
dont need it rn
but we dont need to block it
yeah, you'd have to name the page like _.vue and then handle all routing in the component https://nuxtjs.org/docs/2.x/features/file-system-routing#unknown-dynamic-nested-routes
so like page/_.vue will handle page/test1/test2/test3/test4/ and page/test1, etc
I just was confused since webstorm wasnt finding the watchers prop
it works for me?
I wasted too much time on that
I accessed the prop from the _author/_slug/index.vue page
idk
my brain is ded
but I tried that
even googled why it wasnt working
found the PR that initially implemented it
and it didnt work
hmm, we must've done smth differently or idk. did you define the prop on the child page?
yes
huh... well idk what to say
just commit it yourself and hope it doesnt break here 😂
am face diving my bed now or smth
I hate mondays
@pallid yoke which module did you import Prop from for defining the prop?
🤷♂️
cause it seems it doesnt work if you import it from the nuxt-property-decorator module but DOES work from the vue-property-decorator
which is so stupid
yeah, cause I merged your changes, and it stopped working for me as well
Most likely was the same
well just ignore me, its working now
so idk what the problem was
I restarted the nuxt-dev thing so maybe that was it
good idea to do that after a rebase I think
lol
ok... so now im not sure how to get access to that prop in asyncData since you dont have access to this there
Well like on the docs page, to request the page, we need to know what project to request the page for
Yeah. I guess.
lol had an annoying issue because /api/internal/pages/Machine_Maker/TestProject/
matched to the old /{author}/{slug}/pages/{page}/{subPage}/ route
took me a while to figure out what was happening
so I got project page editing up and running
finishing up the new page modal
this is certainly a process, but its happening slowly
Yeah
I underestimated it too
But once it's done we fully own the full stack and it will be easy to maintain
well imagine doing this w/o a component library...
Well, we would have sticked with bootstrap or smth
