This page describes Calíope 1.5, the version I am building right now. 1.4 is on the App Store for the Mac, iPad, iPhone, Apple Watch, Apple TV and Apple Vision Pro. The changelog says which version each feature landed in.
Adds an “Open in Calíope” button to every topic. It only works with the app installed.
Create, edit and delete server accounts along with their privileges.
Where it is: Workspace › Tools › Users
Open Users from the workspace navigation bar. The left panel lists every account on the server, with the ones the server installs grouped separately; the search field filters by name. Select an account to load its privileges.
What appears on the right depends on the engine, because the security model is not the same. In MySQL and MariaDB an account is user@host and privileges are granted at four scopes: Global, Database, Table and Routine. In PostgreSQL an account is a role, there is no host, and instead of the global scope you get its attributes, which are not granted but set. What an engine does not have is not drawn greyed out: it is not drawn.
Inside each card the checkboxes are grouped by Data, Structure, Routines, Administration and Replication. Tick what applies and press Save changes; while there are unsaved changes the header says so, and Discard changes goes back to what is on the server.
In SQL Server an account is a server login, with no host; in each database it acts through the user linked to it, which Calíope finds on its own. Privileges go at five scopes —Global (the server), Connection (a database), Database (a schema), Table and Routine— and a DENY is shown as a third state, crossed out and named: here it can be seen but not changed; it is set and removed from the SQL Editor.
Without permission to read the accounts — in MySQL and MariaDB, SELECT on the mysql database — the list says “Couldn’t read the server’s accounts”, with the server's reason underneath and a button to retry, and the footer shows no count. In PostgreSQL it does not happen: any account can read the roles. In SQL Server, without VIEW ANY DEFINITION you see fewer accounts, with no error. And in Backups, without that permission the server accounts section does not appear.
Keywords: users, roles, privileges, permissions, GRANT, user admin
Press New user in the Users bar. Enter the name, the host and the password. The account is created with no privileges and is left selected, so you can assign them right away.
The host field and the authentication method picker only appear where the engine has them. PostgreSQL has neither: where a connection is accepted from is decided by the server’s pg_hba.conf, and how the password is encrypted is decided by the server configuration, not by the account. The role is created with LOGIN and INHERIT, as CREATE USER does, so it can sign in; its other attributes are ticked afterwards on its own card.
SQL Server doesn't have them either: the account is a login, with no host and no method to choose.
Keywords: create user, new user, CREATE USER, password
Select the account in the left panel and press Delete in the header. A confirmation dialog shows what will be removed. The action cannot be undone.
The accounts the server installs appear in their own group and cannot be deleted from here.
In PostgreSQL the server may refuse, and that is not a Calíope bug: a role that owns objects or holds granted privileges cannot be dropped until those are removed. Calíope does not issue DROP OWNED BY on its own, because that would delete data nobody asked to delete. Remove its grants first —including the “all tables” ones, which also leave a default privilege behind— or reassign what it owns.
In SQL Server deleting removes the account's user in every database and then the login. The server refuses while one of those users owns a schema: hand the schema to someone else first (ALTER AUTHORIZATION).
Select the account in the left panel and press Edit in the header. The edit form opens.
The form only shows what the engine has. In MySQL and MariaDB it carries the password, the authentication method, the account lock and the hourly resource limits. In PostgreSQL it carries the password and nothing else: there is no lock —an account is closed by removing its LOGIN attribute, which is on its own card— and no hourly limits, while the concurrent connection count and the expiry date are edited next to the attributes.
The form opens with what the server has: whether the account is locked and its hourly limits. A limit of 0 means no limit, and setting one back to 0 removes it. Leave the password field empty if you only want to change the other settings.
In SQL Server it carries the password and the lock (ALTER LOGIN … DISABLE: the login can't sign in and keeps its permissions); there are no hourly limits and no expiry date per account.
Keywords: change password, password, edit user, ALTER USER, credentials, new password
Assign granular permissions at the database, table, or specific routine level.
Where it is: Users › Privileges tree
Each privilege scope is a card with its granted counter and its WITH GRANT OPTION switch:
- Role attributes — PostgreSQL only. These are not privileges: they are properties of the role (LOGIN, SUPERUSER, CREATEDB…) written with ALTER ROLE. Concurrent connections and the expiry date sit at the bottom.
- Global — MySQL family and SQL Server. They apply to the whole server (e.g. SUPER or PROCESS in MySQL, VIEW SERVER STATE in SQL Server).
- Connection — PostgreSQL and SQL Server. In PostgreSQL, the privileges of the cluster database the profile points at: CONNECT, CREATE and TEMPORARY, which decide whether the account can connect at all. In SQL Server, those over a whole database (CONNECT, CREATE TABLE…).
- Database — over every object in a database (in PostgreSQL and SQL Server, of a schema).
- Table — over one specific table.
- Routine — over a stored procedure or function.
Inside each card the checkboxes are grouped by category, with Select all per group, and ALL PRIVILEGES is highlighted at the top because it grants the whole scope at once.
To add a scope that is not listed, use Add object in the bottom bar. Save changes runs the required REVOKE and GRANT statements; if the server rejects any, a notice appears next to the button with the detail.
Why this screen does not look like the MySQL one, and what each part means.
Where it is: Workspace › Tools › Users
PostgreSQL has no separate users and groups: it has roles, and a role is both at once. A role with the LOGIN attribute can sign in; one without it exists to group privileges and hand them to others. That is why the screen changes shape, and not on a whim.
There is no host. An account is a bare name. Where a connection is accepted from is decided by pg_hba.conf, which belongs to the server and not to the account, so Calíope neither shows it here nor can change it.
Attributes are not privileges.SUPERUSER, CREATEDB, CREATEROLE, REPLICATION, BYPASSRLS, INHERIT and LOGIN are set with ALTER ROLE, not granted with GRANT. On save, Calíope writes all of them: whatever you leave unticked is turned off. That is what makes the screen truthful — if only the ticked ones were written, unticking a box would not turn it off and it would come back on its own the next time you opened the account.
Membership is transitive. If app is a member of readers and readers of auditors, then app has what auditors has without anyone granting it. The Member of card tells direct memberships from inherited ones and shows the path of each. Inherited ones cannot be removed from here, which is why they have no button: what would have to be revoked is the link, and that link belongs to another role.
PUBLIC is not a role: it is everyone. It appears in the list as one more account because otherwise an object granted to everyone would look private. By default PUBLIC may connect to the database and execute any function.
The owner has everything over what it owns, and that never appears as a grant. A freshly created table has no privilege rows in the catalogue at all, and its owner can still do whatever it likes with it. That is why the header carries the “owns N objects” badge and those cards are drawn ticked and greyed out: there is nothing to grant and nothing to revoke.
“Grant on all tables” is two statements. In MySQL, ON database.* also covers tables created tomorrow; here it takes two commands that do not mean the same thing: one reaches the tables that exist now and the other the future ones. The second one, moreover, only covers those created by the account Calíope is connected with. Neither comes back afterwards as a checkbox on the schema card, because they are not schema privileges. The button next to it undoes both, and it is needed: while the default privilege remains, the server will not let you delete the account.
What is missing. There is no account lock —you remove LOGIN—, no hourly limits —only the concurrent connection count—, no authentication method picker —the server decides— and no FLUSH PRIVILEGES: here the catalogue is the source, and a GRANT is already in force by the time the server answers.