From 3cd0fa9e269fbd8a7f8a3306a196f0282dea4e06 Mon Sep 17 00:00:00 2001 From: florian <f.spreckelsen@inidscale.com> Date: Fri, 23 Jul 2021 10:18:43 +0200 Subject: [PATCH] MAINT: Move Connection module to separate file --- src/CaosDB.jl | 357 +------------------------------------------ src/Connection.jl | 380 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 381 insertions(+), 356 deletions(-) create mode 100644 src/Connection.jl diff --git a/src/CaosDB.jl b/src/CaosDB.jl index 5d09f41..7daec21 100644 --- a/src/CaosDB.jl +++ b/src/CaosDB.jl @@ -138,362 +138,7 @@ end end # Authentication -module Connection - -using ..CaosDB - -export connect - -""" -Struct containing the actual connection to a CaosDB server. Meant for -internal use; call a `CaosDB.Connection.create_<connection>` function -to create an connection object from a configuration. -""" -mutable struct _Connection - wrapped_connection::Ptr{Cvoid} - - function _Connection() - conn = new() - conn.wrapped_connection = C_NULL - function f(t) - if t.wrapped_connection != C_NULL - ccall( - (:caosdb_connection_delete_connection, "libccaosdb"), - Cint, - (Ref{_Connection},), - Ref{_Connection}(t), - ) - end - end - finalizer(f, conn) - end -end - -""" -Struct containing a pointer to the wrapped cpp class providing the -certificate provider. Meant for internal use; call a -`CaosDB.Connection.create_<certificate_provider>` function to create -an certificate-provider object from a configuration. -""" -mutable struct _CertificateProvider - wrapped_certificate_provider::Ptr{Cvoid} - - function _CertificateProvider() - prov = new() - prov.wrapped_certificate_provider = C_NULL - function f(t) - if t.wrapped_certificate_provider != C_NULL - ccall( - (:caosdb_connection_delete_certificate_provider, "libccaosdb"), - Cint, - (Ref{_CertificateProvider},), - Ref{_CertificateProvider}(t), - ) - end - end - finalizer(f, prov) - end -end - -""" -Struct containing a pointer to the wrapped cpp class for storing the -connection configuration. Meant for internal use; call a -`CaosDB.Connection.create_<configuration>` function to create -an connection-configuration object from a configuration. -""" -mutable struct _Configuration - wrapped_connection_configuration::Ptr{Cvoid} - - function _Configuration() - config = new() - config.wrapped_connection_configuration = C_NULL - function f(t) - if t.wrapped_connection_configuration != C_NULL - ccall( - (:caosdb_connection_delete_connection_configuration, "libccaosdb"), - Cint, - (Ref{_Configuration},), - Ref{_Configuration}(t), - ) - end - end - finalizer(f, config) - end -end - -""" - create_pem_file_certificate_provider(path::AbstractString) - -Return a `_CertificateProvider` for the pem certificate located at -`path`. -""" -function create_pem_file_certificate_provider(path::AbstractString) - - cert_provider = Ref{_CertificateProvider}(_CertificateProvider()) - - err_code = ccall( - (:caosdb_connection_create_pem_file_certificate_provider, "libccaosdb"), - Cint, - (Ref{_CertificateProvider}, Cstring), - cert_provider, - path, - ) - - if err_code != 0 - - @error "PEM certificate creation returned code $err_code." - - end - - return cert_provider - -end - -""" - create_tls_connection_configuration( - host::AbstractString, - port::Cint, - authenticator::Ref{CaosDB.Authentication._Authenticator}, - provider::Ref{_CertificateProvider} - ) - -Return a TLS connection configuration with authentication. -""" -function create_tls_connection_configuration( - host::AbstractString, - port::Cint, - authenticator::Ref{CaosDB.Authentication._Authenticator}, - provider::Ref{_CertificateProvider}, -) - - config = Ref{_Configuration}(_Configuration()) - - err_code = ccall( - (:caosdb_connection_create_tls_connection_configuration, "libccaosdb"), - Cint, - ( - Ref{_Configuration}, - Cstring, - Cint, - Ref{CaosDB.Authentication._Authenticator}, - Ref{_CertificateProvider}, - ), - config, - host, - port, - authenticator, - provider, - ) - - if err_code != 0 - - @error "TLS-configuration creation returned code $err_code." - - end - - return config - -end - -function create_insecure_connection_configuration(host::AbstractString, port::Cint) - - config = Ref{_Configuration}(_Configuration()) - - err_code = ccall( - (:caosdb_connection_create_insecure_connection_configuration, "libccaosdb"), - Cint, - (Ref{_Configuration}, Cstring, Cint), - config, - host, - port, - ) - - if err_code != 0 - - @error "Insecure configuration creation returned code $err_code." - - end - - return config -end - -""" - create_connection(config::Ref{_Configuration}) - -Return a connection based on the given `config`. -""" -function create_connection(config::Ref{_Configuration}) - - connection = Ref{_Connection}(_Connection()) - - err_code = ccall( - (:caosdb_connection_create_connection, "libccaosdb"), - Cint, - (Ref{_Connection}, Ref{_Configuration}), - connection, - config, - ) - - if err_code != 0 - - @error "Creating connection failed with code $err_code." - - end - - return connection - -end - -""" - get_version_info(con::Ref{_Connection}) - -Return the version of the CaosDB server that `con` is connected -to. -""" -function get_version_info(con::Ref{_Connection}) - - info = Ref{CaosDB.Info._VersionInfo}(CaosDB.Info._VersionInfo()) - - err_code = ccall( - (:caosdb_connection_get_version_info, "libccaosdb"), - Cint, - (Ref{CaosDB.Info._VersionInfo}, Ref{_Connection}), - info, - con, - ) - - # TODO Real error-code handling - if err_code != 0 - - @error "Version info returned with code $err_code" - - end - - return info - -end - -""" - print_version_info(con::Ref{_Connection}) - -Retrieve the version info for the CaosDB server `con` is connected to, -and print the version in a nice message. -""" -function print_version_info(con::Ref{_Connection}) - - # Dereference to access the fields - info = get_version_info(con)[] - - major = info.major - minor = info.minor - patch = info.patch - pre_release_str = unsafe_string(info.pre_release) - build_str = unsafe_string(info.build) - - println( - "Connected to a CaosDB server with version $major.$minor.$patch-$pre_release_str-$build_str.", - ) - -end - -""" - function connect([; - host::AbstractString="", - port_str::AbstractString="undefined", - cacert::AbstractString="", - username::AbstractString="", - password::AbstractString="undefined"] - ) - -Return a connection object created for the given `host`:`port` with an -SSL certificate located at `cacert` with the given credentials. - -# Extended help - -!!! info - - Because of type-stability, and since an empty string may be a - valid password, the value of `password`, for which it is fetched - from an environmental variable, is "undefined". This means that if - you absolutely must use "undefined" as your password, you have to - specify it via the `CAOSDB_PASSWORD` variable. - -# Arguments -- `host::AbstractString=""`: The hostname of the CaosDB server. If - none is provided, the `CAOSDB_SERVER_HOST` environmental variable is - used instead. If that's not defined, "localhost" is used. -- `port_str::AbstractString="undefined"`: The port of the CaosDB - server, given as string. If none is provided, the - `CAOSDB_SERVER_GRPC_PORT_HTTPS` environmental variable is used - instead. If that's not defined, "8443" is used. The default value is - "undefined" rather than an empty string because an empty string - could be a valid port, too, i.e. the CaosDB server is available at - `host` without a port. -- `cacert::AbstractString=""`: The path to the SSL certificate of the - CaosDB server. If none is provided, the `CAOSDB_SERVER_CERT` - environmental variable is used instead. -- `username::AbstractString=""`: The username with which to log in - into the CaosDB server. If none is provided, the `CAOSDB_USER` - environmental variable is used instead. If that's not defined, - "admin" is used. -- `password::AbstractString="undefined"`: The password with which to - log in into the CaosDB server. If none is provided, the - `CAOSDB_PASSWORD` environmental variable is used instead. If that's - not defined, "caosdb" is used. The default value is "undefined" - rather than an empty string to allow an empty password. -""" -function connect(; - host::AbstractString = "", - port_str::AbstractString = "undefined", - cacert::AbstractString = "", - username::AbstractString = "", - password::AbstractString = "undefined", -) - - if host == "" - - host = CaosDB.Utility.get_env_var("CAOSDB_SERVER_HOST", "localhost") - - end - - if port_str == "undefined" - - port_str = CaosDB.Utility.get_env_var("CAOSDB_SERVER_GRPC_PORT_HTTPS", "8443") - - end - - port = parse(Cint, port_str) - - if cacert == "" - - cacert = CaosDB.Utility.get_env_var("CAOSDB_SERVER_CERT") - - end - - if username == "" - - username = CaosDB.Utility.get_env_var("CAOSDB_USER", "admin") - - end - - if password == "undefined" - - password = CaosDB.Utility.get_env_var("CAOSDB_PASSWORD", "caosdb") - - end - - provider = create_pem_file_certificate_provider(cacert) - authenticator = - CaosDB.Authentication.create_plain_password_authenticator(username, password) - config = create_tls_connection_configuration(host, port, authenticator, provider) - connection = create_connection(config) - print_version_info(connection) - - return connection - -end - -end # Connection +include("Connection.jl") module Entity end diff --git a/src/Connection.jl b/src/Connection.jl new file mode 100644 index 0000000..7c713bf --- /dev/null +++ b/src/Connection.jl @@ -0,0 +1,380 @@ +# ** header v3.0 +# This file is a part of the CaosDB Project. +# +# Copyright (C) 2021 Indiscale GmbH <info@indiscale.com> +# Copyright (C) 2021 Florian Spreckelsen <f.spreckelsen@indiscale.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with this program. If not, see +# <https://www.gnu.org/licenses/>. +# +# ** end header +# + +module Connection + +using ..CaosDB + +export connect + +""" +Struct containing the actual connection to a CaosDB server. Meant for +internal use; call a `CaosDB.Connection.create_<connection>` function +to create an connection object from a configuration. +""" +mutable struct _Connection + wrapped_connection::Ptr{Cvoid} + + function _Connection() + conn = new() + conn.wrapped_connection = C_NULL + function f(t) + if t.wrapped_connection != C_NULL + ccall( + (:caosdb_connection_delete_connection, "libccaosdb"), + Cint, + (Ref{_Connection},), + Ref{_Connection}(t), + ) + end + end + finalizer(f, conn) + end +end + +""" +Struct containing a pointer to the wrapped cpp class providing the +certificate provider. Meant for internal use; call a +`CaosDB.Connection.create_<certificate_provider>` function to create +an certificate-provider object from a configuration. +""" +mutable struct _CertificateProvider + wrapped_certificate_provider::Ptr{Cvoid} + + function _CertificateProvider() + prov = new() + prov.wrapped_certificate_provider = C_NULL + function f(t) + if t.wrapped_certificate_provider != C_NULL + ccall( + (:caosdb_connection_delete_certificate_provider, "libccaosdb"), + Cint, + (Ref{_CertificateProvider},), + Ref{_CertificateProvider}(t), + ) + end + end + finalizer(f, prov) + end +end + +""" +Struct containing a pointer to the wrapped cpp class for storing the +connection configuration. Meant for internal use; call a +`CaosDB.Connection.create_<configuration>` function to create +an connection-configuration object from a configuration. +""" +mutable struct _Configuration + wrapped_connection_configuration::Ptr{Cvoid} + + function _Configuration() + config = new() + config.wrapped_connection_configuration = C_NULL + function f(t) + if t.wrapped_connection_configuration != C_NULL + ccall( + (:caosdb_connection_delete_connection_configuration, "libccaosdb"), + Cint, + (Ref{_Configuration},), + Ref{_Configuration}(t), + ) + end + end + finalizer(f, config) + end +end + +""" + create_pem_file_certificate_provider(path::AbstractString) + +Return a `_CertificateProvider` for the pem certificate located at +`path`. +""" +function create_pem_file_certificate_provider(path::AbstractString) + + cert_provider = Ref{_CertificateProvider}(_CertificateProvider()) + + err_code = ccall( + (:caosdb_connection_create_pem_file_certificate_provider, "libccaosdb"), + Cint, + (Ref{_CertificateProvider}, Cstring), + cert_provider, + path, + ) + + if err_code != 0 + + @error "PEM certificate creation returned code $err_code." + + end + + return cert_provider + +end + +""" + create_tls_connection_configuration( + host::AbstractString, + port::Cint, + authenticator::Ref{CaosDB.Authentication._Authenticator}, + provider::Ref{_CertificateProvider} + ) + +Return a TLS connection configuration with authentication. +""" +function create_tls_connection_configuration( + host::AbstractString, + port::Cint, + authenticator::Ref{CaosDB.Authentication._Authenticator}, + provider::Ref{_CertificateProvider}, +) + + config = Ref{_Configuration}(_Configuration()) + + err_code = ccall( + (:caosdb_connection_create_tls_connection_configuration, "libccaosdb"), + Cint, + ( + Ref{_Configuration}, + Cstring, + Cint, + Ref{CaosDB.Authentication._Authenticator}, + Ref{_CertificateProvider}, + ), + config, + host, + port, + authenticator, + provider, + ) + + if err_code != 0 + + @error "TLS-configuration creation returned code $err_code." + + end + + return config + +end + +function create_insecure_connection_configuration(host::AbstractString, port::Cint) + + config = Ref{_Configuration}(_Configuration()) + + err_code = ccall( + (:caosdb_connection_create_insecure_connection_configuration, "libccaosdb"), + Cint, + (Ref{_Configuration}, Cstring, Cint), + config, + host, + port, + ) + + if err_code != 0 + + @error "Insecure configuration creation returned code $err_code." + + end + + return config +end + +""" + create_connection(config::Ref{_Configuration}) + +Return a connection based on the given `config`. +""" +function create_connection(config::Ref{_Configuration}) + + connection = Ref{_Connection}(_Connection()) + + err_code = ccall( + (:caosdb_connection_create_connection, "libccaosdb"), + Cint, + (Ref{_Connection}, Ref{_Configuration}), + connection, + config, + ) + + if err_code != 0 + + @error "Creating connection failed with code $err_code." + + end + + return connection + +end + +""" + get_version_info(con::Ref{_Connection}) + +Return the version of the CaosDB server that `con` is connected +to. +""" +function get_version_info(con::Ref{_Connection}) + + info = Ref{CaosDB.Info._VersionInfo}(CaosDB.Info._VersionInfo()) + + err_code = ccall( + (:caosdb_connection_get_version_info, "libccaosdb"), + Cint, + (Ref{CaosDB.Info._VersionInfo}, Ref{_Connection}), + info, + con, + ) + + # TODO Real error-code handling + if err_code != 0 + + @error "Version info returned with code $err_code" + + end + + return info + +end + +""" + print_version_info(con::Ref{_Connection}) + +Retrieve the version info for the CaosDB server `con` is connected to, +and print the version in a nice message. +""" +function print_version_info(con::Ref{_Connection}) + + # Dereference to access the fields + info = get_version_info(con)[] + + major = info.major + minor = info.minor + patch = info.patch + pre_release_str = unsafe_string(info.pre_release) + build_str = unsafe_string(info.build) + + println( + "Connected to a CaosDB server with version $major.$minor.$patch-$pre_release_str-$build_str.", + ) + +end + +""" + function connect([; + host::AbstractString="", + port_str::AbstractString="undefined", + cacert::AbstractString="", + username::AbstractString="", + password::AbstractString="undefined"] + ) + +Return a connection object created for the given `host`:`port` with an +SSL certificate located at `cacert` with the given credentials. + +# Extended help + +!!! info + + Because of type-stability, and since an empty string may be a + valid password, the value of `password`, for which it is fetched + from an environmental variable, is "undefined". This means that if + you absolutely must use "undefined" as your password, you have to + specify it via the `CAOSDB_PASSWORD` variable. + +# Arguments +- `host::AbstractString=""`: The hostname of the CaosDB server. If + none is provided, the `CAOSDB_SERVER_HOST` environmental variable is + used instead. If that's not defined, "localhost" is used. +- `port_str::AbstractString="undefined"`: The port of the CaosDB + server, given as string. If none is provided, the + `CAOSDB_SERVER_GRPC_PORT_HTTPS` environmental variable is used + instead. If that's not defined, "8443" is used. The default value is + "undefined" rather than an empty string because an empty string + could be a valid port, too, i.e. the CaosDB server is available at + `host` without a port. +- `cacert::AbstractString=""`: The path to the SSL certificate of the + CaosDB server. If none is provided, the `CAOSDB_SERVER_CERT` + environmental variable is used instead. +- `username::AbstractString=""`: The username with which to log in + into the CaosDB server. If none is provided, the `CAOSDB_USER` + environmental variable is used instead. If that's not defined, + "admin" is used. +- `password::AbstractString="undefined"`: The password with which to + log in into the CaosDB server. If none is provided, the + `CAOSDB_PASSWORD` environmental variable is used instead. If that's + not defined, "caosdb" is used. The default value is "undefined" + rather than an empty string to allow an empty password. +""" +function connect(; + host::AbstractString = "", + port_str::AbstractString = "undefined", + cacert::AbstractString = "", + username::AbstractString = "", + password::AbstractString = "undefined", +) + + if host == "" + + host = CaosDB.Utility.get_env_var("CAOSDB_SERVER_HOST", "localhost") + + end + + if port_str == "undefined" + + port_str = CaosDB.Utility.get_env_var("CAOSDB_SERVER_GRPC_PORT_HTTPS", "8443") + + end + + port = parse(Cint, port_str) + + if cacert == "" + + cacert = CaosDB.Utility.get_env_var("CAOSDB_SERVER_CERT") + + end + + if username == "" + + username = CaosDB.Utility.get_env_var("CAOSDB_USER", "admin") + + end + + if password == "undefined" + + password = CaosDB.Utility.get_env_var("CAOSDB_PASSWORD", "caosdb") + + end + + provider = create_pem_file_certificate_provider(cacert) + authenticator = + CaosDB.Authentication.create_plain_password_authenticator(username, password) + config = create_tls_connection_configuration(host, port, authenticator, provider) + connection = create_connection(config) + print_version_info(connection) + + return connection + +end + +end # Connection + -- GitLab