-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add last active admin functionality #214
Conversation
The implementation is mostly based on DU4L#16 but we update the timer in the database instead of the frontend. The update is done when the user fetches the profile, so for every first load done in a new tab in the browser. Please note that this commit can NOT be merged before TFNS#213 is merged since the migration files are now not consecutive. The other PR contains a migration with ID 41, so this PR has a migration with ID 42 (and this answers everything of course). The migration will fail in this branch therefore. For testing, please rename the file and use a throw away database.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting addition.
From my understanding, the last active date should only be visible by users with admin privileges. (and I agree)
Unfortunately this is not the case -- guests can access this information too by looking at the response of the getTeam
operation.
% curl -s 'http://localhost:8080/graphql' -H 'content-type: application/json' -H "authorization: Bearer $token" --data-raw '[{"operationName":"getTeam","variables":{},"query":"query getTeam {\n profiles {\n nodes {\n ...ProfileFragment\n __typename\n }\n __typename\n }\n}\n\nfragment ProfileFragment on Profile {\n id\n username\n lastactive\n color\n description\n role\n nodeId\n __typename\n}\n"}]' | jq '.[0].data.profiles.nodes[] | {username, lastactive}'
{
"username": "a",
"lastactive": "2023-05-09T23:50:39.634667+00:00"
}
{
"username": "x",
"lastactive": "2023-05-10T00:08:53.204503+00:00"
}
% echo $token | cut -f2 -d. | base64 -d
{"user_id":2,"role":"user_guest","exp":1686268296,"iat":1683676296,"aud":"postgraphile","iss":"postgraphile"}
@XeR, thanks for reviewing the code! The PR of DU4L already contained this in their PR description:
However, I agree with your view that it is more expected by users to have this admin-only since the UI is implemented this way too. I will fix this soon. Related question: do you know any good way of viewing the current permission model of the postgresql database? As far as I know, the only way is to read all migrations and track the permissions yourself to get a clear overview of what is allowed for which role. |
This implementation almost works, but fails in the websocket subscription. Therefore, we change to column wise security.
Now the row `lastactive` is only accessible by the admin. The public profile is accessed everywhere and in the admin view the whole profile is queried. For the me() function, we have to output a valid ctfnote.profile but we can't access the `lastactive` column, so we replace it with NULL by default. This fixes the problem we faced in the row wise security model.
@XeR, in the end I have added column security to the |
I tested again. I'm afraid the problem is still there. :-(
Redirecting this question to @B-i-t-K |
This reverts commit 5fdb25b.
The websocket implementation has been changed to manual by following https://www.graphile.org/postgraphile/subscriptions/. This was required since the default implementation returns a profile, which is restricted in access. Now a public profile is returned which is not restricted. All functionalities should stay the same. You are only able to query your own last active date but not from other profiles. Column wise security was not possible to fully complete since relations between objects will break due to internal postgraphile stuff. For example, postgraphile likes to use * internally which won't work with column security.
@XeR, I had to revert the column wise security since postgraphile doesn't like that if you fully enforce the access (I didn't drop the previous privileges, that is why you were able to query it through the old method). I have now reverted to the row wise security and implemented the websocket part through the manual method of postgraphile. The websocket now broadcasts the public profile while it is still being triggered by a (private) profile update. I was able to reproduce your query through the JavaScript console and have now verified that you are only able to query the last active information of yourself. Can you also check again? |
Hi, I tested commit 54639c2 with a new environment ( Now the boring part : this is personal data. I'd love to have the input of the users about this. |
For me this feature was useful to get more insight in the large amount of user accounts created in the past few years. Now I can easily see that a lot of accounts are not used anymore and can safely delete them. I didn't think of using this as an activity tracker for CTF participation. It is also totally not accurate for that, since it will only update the timestamp on a first load of the page (for example by opening CTFNote in a new tab or reloading the page).
I think this can be more easily answered by checking the "on it" status of the tasks during the CTF. That is an easier way to blame specific users if they only solve the welcome challenge and nothing else ;) |
My take on the GDPR (I am not a lawyer btw):
The GDPR defines personal data as:
From a timestamp, I would not be able to identify a specific user. Instead the usernames the users provide could be personal data, since they can be their real name for example. As stated in my previous comment, with the timestamp it is easier to identify inactive accounts. This makes it easier to fulfill article 5 1(e):
Now I can know when I should start deleting their accounts, including their usernames which can be classified as personal data, in order to ensure that I don't store it for longer than necessary. Therefore, I think it is fair to say that we can use article 6 1(f) as a lawful base for processing the users last activity timestamp so we can more accurately perform the task described in article 5 1(e). |
Ah, fair point.
A personal data is a data that is related to an data subject.
It does not have to point to somebody in meat space for it to be considered "personal data". |
I don't think this applies here in general, since you @XeR are not the one collecting the data in some CTFNote as a Service business, where you host the data for someone else. The GDPR doesn't apply in personal context. The teams hosting the tool for their friends and members are responsible to decide which data they want to store. Since I assume you're hosting CTFNote yourself though, this feature should be designed in a way, that you're comfortable hosting your own software. So I'd propose a switch in the admin panel to toggle storing the timestamp and showing a notice in the login form when the timestamp is collected. That way everyone can decide for their own if their setup is large enough to disable the feature. |
The implementation is mostly based on DU4L#16 but we update the timer in the database instead of the frontend. The update is done when the user fetches the profile, so for every first load done in a new tab in the browser.
Please note that this commit can NOT be merged before #213 is merged since the migration files are now not consecutive. The other PR contains a migration with ID 41, so this PR has a migration with ID 42 (and this answers everything of course). The migration will fail in this branch therefore. For testing, please rename the file and use a throw away database.