Split up Metadata Interface for backend

Hi @stefan.feilmeier I wanted suggest an architectural change in your Metadata Backend interface
io.openems.backend.common.metadata.Metadata

Currently this interfaces combines Metadata for User and for Edge in a single interface. This prevents me from implementing an alternative User-Backend while still keeping Edge-Information in a file or elsewhere.

This could work out since it’s only the users that need to know about Edges.

Hi Simon,

yes, that sounds absolutely feasible. Metadata just somehow evolved from how we use it in the Odoo backend:

I know that opernikus was doing some development for integrating with Keycloak. @c.lehne: any ideas or remarks about this approach?

https://www.keycloak.org/

Regards,
Stefan

Hi Simon,

as @stefan.feilmeier remarks we are working on a keycloak integration. We are reworking the bundle right now, because we also want to use the postgresql functionality of the odoo bundle. Thats why the bundle is not yet published.
You are right, the Metadata interface is a bit unclean from an architectural point of view. That in mind, we have already separated our bundle implementation into

EdgeHandler
  public abstract Optional<String> getEdgeIdForApikey(String apikey);
  public abstract Optional<Edge> getEdge(String edgeId);
  public default Edge getEdgeOrError(String edgeId);
  public abstract Optional<Edge> getEdgeBySetupPassword(String setupPassword);
  public abstract Collection<Edge> getAllEdges();

and

UserHandler
   public User authenticate(String username, String password);
   public MyUser authenticate(String token);
   public void logout(User user);
   public Optional<User> getUser(String userId);
   public void addEdgeToUser(User user, Edge edge);
   public void updateUserLanguage(User user, Language language);
   public Map<String, Object> getUserInformation(User user);
   public void setUserInformation(User user, JsonObject jsonObject);
   public byte[] getSetupProtocol(User user, int setupProtocolId);
   public int submitSetupProtocol(User user, JsonObject jsonObject);
   public void registerUser(JsonObject jsonObject);

This separation might be a good starting point for a separation of the Metadata interface also.
One could extract the edge methods from the Metadata interface, put them in a MetadataEdge interface
and modify

Metadata
    public MetadataEdge getMetadataEdge();
    ...

I am a bit unsure of the implications this might have!
For example, how do we use metadata.file for Edge handling and metadata.<mynewuserbundle> for user handling and how do we use them together?

Regards, Chris

1 Like

Hi @c.lehne ,

that new interface design would make integration of authentication service providers a lot easier.

If you plan to avoid any implications on other services you could create a proxy service:

Metadataservice implements Metadata
@Reference
protected volatile UserHandler userHandler;
@Reference
protected volatile EdgeHandler edgeHandler;

This would ensure EdgeWebsocket and others that bind Metadata will not be affected.

Best regards!

Hi @c.lehne and @stefan.feilmeier i opened a draft PR for this purpose.
Would love to get some feedback. I tried to not brick the odoo implementation so far.

My overall goal is to use the FileMetadata for Edges and implement another authentication handler (that I would aswell make open-source).

split backend metadata interface into edge and auth metadata by simonfey · Pull Request #1795 · OpenEMS/openems (github.com)

Hi all,

I am aware I am reopening an old topic, but this discussion is interesting to me as I have been implementing a new Metadata provider which uses Keycloak for authentication and Postgres for storing user and edge metadata.

My implementation is largely based on the structure of the Odoo metadata provider in that I have a PostgresHandler and a KeycloakHandler.

Keycloak is being used for user authentication and storing/validation of user credentials and Postgres is used to store additional metadata about the user and the edges.

I have basically reused the PostgresHandler implementation from the OdooMetadata but changing the queries and methods to match the altered table structure that I am using.

It sounds like @c.lehne and Opernikus may have done something similar.

As of now my code is a bit untidy and the implementation is not complete, but I would be willing to share my code in a PR if there was interest in incorporating this into OpenEMS.