Skip to content
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

[Feature Request] Disable topic subscriptions through admin API #722

Closed
CreativeWarlock opened this issue May 12, 2023 · 16 comments
Closed
Labels
enhancement New feature or request server Relates to the main binary (server or client)

Comments

@CreativeWarlock
Copy link

CreativeWarlock commented May 12, 2023

Hello mate,

For a small startup business that a friend and I have been creating and which would integrate your cool notication service, we got a little feature request for NTFY.sh that allows managing user subscriptions through a given admin user, preferrably via POST requests.

The following diagram shows a simplified model of our business, where users pay for accessing signal services that send data over different NTFY topics (represented by Channel A, B, C).

Topics_For_Subscriptions-Seite-2 drawio

For the case that our customers cancel their subcriptions with one of our products, we need something like a flag that can be toggled on/off via admin user (or however you think it best to realize) to ensure that messages are no longer forwarded to a user's endpoint (phone).

This would be beneficial to keep the number of topics small (T=1 topic for N users) rather than setting up individual topics, resulting in T x N topics. It would also reduce the customer's time to setup the topics on the phone with ideally short topic names.

Would this be technically easy to realize? Let me know if you need additional information.

Kind regards
Marcel

@CreativeWarlock CreativeWarlock added the enhancement New feature or request label May 12, 2023
@CreativeWarlock CreativeWarlock changed the title Disable user subscribers through admin API [Feature Request] Disable user subscribers through admin API May 12, 2023
@CreativeWarlock CreativeWarlock changed the title [Feature Request] Disable user subscribers through admin API [Feature Request] Disable topic subscriptions through admin API May 12, 2023
@binwiederhier binwiederhier added the server Relates to the main binary (server or client) label May 13, 2023
@binwiederhier
Copy link
Owner

binwiederhier commented May 13, 2023

This video shows a new endpoint v1/access that lets you control the access control list via an API (admin user only!): https://docs.ntfy.sh/config/#access-control

In the example, use phil is an admin, and is using the API to create an ACL entry for user phil1 (which is not an admin). After the ACL entry is created, phil1 can subscribe to topic gold. After the ACL entry is removed, the user's connection is killed as the access is revoked. Other connections (here: user phil is still subscribed) stay intact.

Create ACL entry (similar to ntfy access command):

curl -s -u phil:phil -d '{"username":"phil1", "topic":"gold","permission":"rw"}' localhost:2586/v1/access

Remove ACL entry:

curl -XDELETE -s -u phil:phil -d '{"username":"phil1", "topic":"gold"}' localhost:2586/v1/access
Screencast_00067.webm

@binwiederhier
Copy link
Owner

WIP PR: #727

@binwiederhier
Copy link
Owner

binwiederhier commented May 14, 2023

I added the following endpoints that can be used as admin user:

  • GET v1/users - List users and user grants (ACL)
  • PUT v1/users - Create a non-admin user and add to tier
  • DELETE v1/users - Delete non-admin user
  • PUT v1/users/access - Add/update ACL entry for a user
  • DELETE v1/users/access Delete ACL entry for a user

Here's an example flow using the new endpoints (updated May 15)

  1. Add user "marcus"
  2. Grant access to topic "gold" + "silver"
  3. List users and user grants
  4. Subscribe to topics "gold" + "silver"
  5. Revoke access from topic "silver" (kills silver topic connection)
  6. Remove user "marcus" (kills gold topic connection)

1. Add user

curl \
  -X PUT \
  -u admin:adminpass \
  -d '{"username":"marcus","password":"marcuspass","tier":"business"}' \
  localhost:2586/v1/users

2. Grant read only access

curl \
  -X POST \
  -u admin:adminpass \
  -d '{"username":"marcus", "topic":"gold","permission":"ro"}' \
  localhost:2586/v1/users/access 
curl \
  -X POST \
  -u admin:adminpass \
  -d '{"username":"marcus", "topic":"silver","permission":"ro"}' \
  localhost:2586/v1/users/access 

3. List users and user grants

curl -su phil:phil localhost:2586/v1/users | jq .                                                                
[
  {
    "username": "phil",
    "role": "admin",
    "tier": "business"   
  },
  {
    "username": "marcus",
    "role": "user",
    "tier": "business",
    "grants": [
      {
        "topic": "gold",
        "permission": "read-only"
      },
      {
        "topic": "silver",
        "permission": "read-only"
      }
    ]
  },
  {
    "username": "*",
    "role": "anonymous"
  }
]

4. Subscribe as "marcus"

curl -u marcus:marcuspass localhost:2586/gold/json   # Connection 1
curl -u marcus:marcuspass localhost:2586/silver/json # Connection 2

5. Revoke access from "silver" (kills connection 2)

curl \
  -X DELETE \
  -u admin:adminpass \
  -d '{"username":"marcus", "topic":"silver"}' \
  localhost:2586/v1/users/access

curl -su phil:phil localhost:2586/v1/users | jq .                                                                
[
  ...
  {
    "username": "marcus",
    "role": "user",
    "tier": "business",
    "grants": [
      {
        "topic": "gold",
        "permission": "read-only"
      }
    ]
  },
  ...
]

6. Delete user "marcus" (kills connection 1)

curl \
  -X DELETE \
  -u admin:adminpass \
  -d '{"username":"marcus"}' \
  localhost:2586/v1/users

@binwiederhier
Copy link
Owner

Sounds good?

@CreativeWarlock
Copy link
Author

Going to test your fast solution after my vacations; I'll be back on Sunday evening, so probably Monday-Tuesday I can test it :)

@binwiederhier
Copy link
Owner

Updated the endpoints and examples again. I think I'm happy with this and will merge it as-is. Given that it won't be released, we can still change it if you like @CreativeWarlock. Enjoy your time off.

@binwiederhier
Copy link
Owner

This is now part of v2.5.0. I'll leave the ticket pending confirmation that this is ok.

@CreativeWarlock
Copy link
Author

The solution seems to fulfill our needs perfectly! I'll update NTFY on my server and need to implement these ACL commands in our backend services. From the looks of your example, I would expect it will work right away. Will report back soon.
So excited! 😄

@CreativeWarlock
Copy link
Author

CreativeWarlock commented May 24, 2023

Small typo found in "1. Add User:"
curl -X PUT -u admin:adminpass -d '{"username":"marcus","password":"marcuspass","tier":"business"}' localhost:2586/v1/users
Response:

{
    "code": 40030,
    "http": 400,
    "error": "invalid request: tier does not exist"
}

('topic' was probably meant, but it's not being used in user creation which is fine as it is 👍 )

All other "CRUD" operations work fine.

@CreativeWarlock
Copy link
Author

CreativeWarlock commented May 24, 2023

I guess in the app on the smartphone, our customers have to add their user name somewhere so that messages can be received on the topics they are subscribed / paying for.

However, if I go to
'settings' -> 'general' -> 'manage users'
and add a new user (I previously created 'hans' and gave it RO permission to some topics), I cannot "create" that new user:

image

Any ideas what I might've done wrong?

@binwiederhier
Copy link
Owner

Small typo found in "1. Add User:" curl -X PUT -u admin:adminpass -d '{"username":"marcus","password":"marcuspass","tier":"business"}' localhost:2586/v1/users Response:

{
    "code": 40030,
    "http": 400,
    "error": "invalid request: tier does not exist"
}

('topic' was probably meant, but it's not being used in user creation which is fine as it is +1 )

This seems correct to me. You are creating a user in this API call, and are assigning the tier business to them. If that tier does not exist, the endpoint will error out. That tier parameter is optional.

User creation does not relate to topics at all. The flow is: (a) you first create a user using v1/users, and then you (b) grant access to a topic using v1/users/access.

However, if I go to 'settings' -> 'general' -> 'manage users' and add a new user (I previously created 'hans' and gave it RO permission to some topics), I cannot "create" that new user

The user management in the Android app is subpar. I will work on that in the near future. For now, you can add an existing (!) user like you said, but you cannot create a user in the Android app. That is correct. I may add that feature later, but it won't help your use case, IMHO.

@CreativeWarlock
Copy link
Author

CreativeWarlock commented May 24, 2023

Thanks for the link to tiers. I have obviously overlooked that feature in your docs.

Yes sadly, if users can't connect to nfty topics through the credentials they get from our system, i.e. after they register & subscribe to our product(s), the business case is not functional and we cannot move on.
Let me know if you need additional infos.

@CreativeWarlock
Copy link
Author

CreativeWarlock commented May 24, 2023

The user management in the Android app is subpar. I will work on that in the near future. For now, you can add an existing (!) user like you said, but you cannot create a user in the Android app.

Wait a sec.. it IS possible to connect with an existing user to the server?
That would be perfectly enough then. Question is: How?

image

That "Benutzer hinzufügen" (Add user) seems to be no link, so idk how to configure the app to use an existing user (that gets created & configured from my backend service).

I'm most likely missing something - so any hint would be much appreciated! :)

@binwiederhier
Copy link
Owner

My apologies for the confusion regarding this "user add" feature.

You are in the correct screen. To add an existing user in the Android app, you have to go to Settings -> Manage users -> Add new user" (Neuen Benutzer hinzufügen). And then add the user for whatever your server is.

The likely reason it didn't work for you above is that you have to prefix the server with "http://" or "https://" in the "Server URL field, e.g. "https://ntfy.example.com" is correct, but "ntfy.example.com" will not work. As I said, the UX is quite annoying. 😬

image

@CreativeWarlock
Copy link
Author

Ah yes, sorry that I didn't try adding the protocol myself.

(Btw. I wrote you on Discord because messages don't come through. It's maybe my server settings or something else is missing between NTFY server and the NTFY app.)

@CreativeWarlock
Copy link
Author

Ok, your feature seems to work fine: I just sent a message to a topic, the NTFY server returned a success response and the message arrives in the app. However, with a delay of 30 minutes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request server Relates to the main binary (server or client)
Projects
None yet
Development

No branches or pull requests

2 participants