Skip to main content

iggy_cli/commands/binary_system/
login.rs

1/* Licensed to the Apache Software Foundation (ASF) under one
2 * or more contributor license agreements.  See the NOTICE file
3 * distributed with this work for additional information
4 * regarding copyright ownership.  The ASF licenses this file
5 * to you under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance
7 * with the License.  You may obtain a copy of the License at
8 *
9 *   http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied.  See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18
19use crate::commands::binary_system::session::ServerSession;
20use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
21use crate::commands::utils::login_session_expiry::LoginSessionExpiry;
22use anyhow::Context;
23use async_trait::async_trait;
24use iggy_common::Client;
25use iggy_common::SEC_IN_MICRO;
26use tracing::{Level, event};
27
28const DEFAULT_LOGIN_SESSION_TIMEOUT: u64 = SEC_IN_MICRO * 15 * 60;
29
30pub struct LoginCmd {
31    server_session: ServerSession,
32    login_session_expiry: Option<LoginSessionExpiry>,
33}
34
35impl LoginCmd {
36    pub fn new(server_address: String, login_session_expiry: Option<LoginSessionExpiry>) -> Self {
37        Self {
38            server_session: ServerSession::new(server_address),
39            login_session_expiry,
40        }
41    }
42}
43
44#[async_trait]
45impl CliCommand for LoginCmd {
46    fn explain(&self) -> String {
47        "login command".to_owned()
48    }
49
50    async fn execute_cmd(&mut self, client: &dyn Client) -> anyhow::Result<(), anyhow::Error> {
51        if self.server_session.is_active() {
52            event!(target: PRINT_TARGET, Level::INFO, "Already logged into Iggy server {}", self.server_session.get_server_address());
53            return Ok(());
54        }
55
56        let tokens = client.get_personal_access_tokens().await.with_context(|| {
57            format!(
58                "Problem getting personal access tokens from server: {}",
59                self.server_session.get_server_address()
60            )
61        })?;
62
63        // If local keyring is empty and server has the token for login session, then something
64        // went wrong, and we should delete the token from the server and recreate login session
65        // from scratch - token on the server and local keyring should be in sync.
66        if let Some(token) = tokens
67            .iter()
68            .find(|pat| pat.name == self.server_session.get_token_name())
69        {
70            client
71                .delete_personal_access_token(&token.name)
72                .await
73                .with_context(|| {
74                    format!(
75                        "Problem deleting old personal access token with name: {}",
76                        self.server_session.get_token_name()
77                    )
78                })?;
79        }
80
81        let token = client
82            .create_personal_access_token(
83                &self.server_session.get_token_name(),
84                match &self.login_session_expiry {
85                    None => Some(DEFAULT_LOGIN_SESSION_TIMEOUT).into(),
86                    Some(value) => *value,
87                },
88            )
89            .await
90            .with_context(|| {
91                format!(
92                    "Problem creating personal access token with name: {}",
93                    self.server_session.get_token_name()
94                )
95            })?;
96
97        self.server_session.store(&token.token)?;
98
99        event!(target: PRINT_TARGET, Level::INFO,
100            "Successfully logged into Iggy server {}",
101            self.server_session.get_server_address(),
102        );
103
104        Ok(())
105    }
106}