KiCad PCB EDA Suite
Loading...
Searching...
No Matches
git_credentials_prompt.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
24#include <confirm.h>
25#include <eda_base_frame.h>
26#include <wx/utils.h>
27#include <wx/weakref.h>
28#include <mutex>
29#include <git/git_backend.h>
32#include <pgm_base.h>
33#include <project.h>
35#include <kiplatform/secrets.h>
36
37
38bool KIGIT::PromptForCredentials( wxWindow* aParent, KIGIT_COMMON* aCommon, PROJECT* aProject )
39{
40 // The dialog seeds its picker from this, so a project that already knows its key does
41 // not make the user find it again.
42 DIALOG_GIT_CREDENTIALS dlg( aParent, aCommon->GetRemote(), aCommon->GetConnType(), aCommon->GetUsername(),
43 aCommon->GetSSHKey() );
44
45 if( dlg.ShowModal() != wxID_OK )
46 return false;
47
48 // An ssh remote's user comes from its address, and the server refuses a different one.
50 aCommon->SetUsername( dlg.GetUsername() );
51
52 aCommon->SetPassword( dlg.GetPassword() );
53
54 if( dlg.GetConnType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH && !dlg.GetSSHKey().IsEmpty() )
55 aCommon->SetSSHKey( dlg.GetSSHKey() );
56
57 if( dlg.SaveCredentials()
58 && !KIPLATFORM::SECRETS::StoreSecret( aCommon->GetRemote(), aCommon->GetUsername(), dlg.GetPassword() ) )
59 {
60 DisplayInfoMessage( aParent, _( "The credentials could not be saved to the system keychain, so they "
61 "are kept for this session only." ) );
62 }
63
64 // A correction only in the session would be reverted by the next attach.
65 if( aProject )
66 {
69
70 if( dlg.GetConnType() == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH && !dlg.GetSSHKey().IsEmpty() )
71 aProject->GetLocalSettings().m_GitSSHKey = dlg.GetSSHKey();
72 }
73
74 aCommon->ClearAuthFailure();
75 aCommon->TestedTypes() = 0;
76 aCommon->ResetNextKey();
77 return true;
78}
79
80
82{
83 GIT_IDENTITY identity;
84
85 if( !aCommon.GetRepo() )
86 return identity;
87
88 GIT_CONFIG_HANDLER handler( &aCommon );
89 identity.config.hasName = GetGitBackend()->GetConfigString( &handler, "user.name", identity.config.authorName );
90 identity.config.hasEmail = GetGitBackend()->GetConfigString( &handler, "user.email", identity.config.authorEmail );
91
92 git_signature* signature = nullptr;
93 identity.configured = git_signature_default( &signature, aCommon.GetRepo() ) == GIT_OK;
94 GitSignaturePtr signaturePtr( signature );
95 return identity;
96}
97
98
100 const wxString& aUserName )
101{
102 GitUserConfig config = aIdentity.config;
103
104 if( !aPreferences.useDefaultAuthor )
105 {
106 if( config.authorName.IsEmpty() )
107 config.authorName = aPreferences.authorName;
108
109 if( config.authorEmail.IsEmpty() )
110 config.authorEmail = aPreferences.authorEmail;
111 }
112
113 if( config.authorName.IsEmpty() )
114 config.authorName = aUserName;
115
116 return config;
117}
118
119
120namespace
121{
122
123bool identitySessionCurrent( EDA_BASE_FRAME* aFrame, const std::shared_ptr<KIGIT_COMMON>& aCommon )
124{
125 return aFrame && !aFrame->IsBeingDeleted() && aCommon && !aCommon->IsShuttingDown() && aCommon->GetRepo()
126 && aFrame->Prj().GetGitCommon() == aCommon && Pgm().GetCommonSettings()->m_Git.enableGit
128}
129
130} // namespace
131
132
133bool KIGIT::EditGitIdentity( wxWindow* aParent, EDA_BASE_FRAME* aFrame, const std::shared_ptr<KIGIT_COMMON>& aCommon,
134 const GIT_IDENTITY& aIdentity )
135{
136 if( !identitySessionCurrent( aFrame, aCommon ) )
137 return false;
138
139 wxWeakRef<EDA_BASE_FRAME> frame( aFrame );
140 wxWeakRef<wxWindow> parent( aParent );
141 GitUserConfig config = ResolveGitIdentity( aIdentity, Pgm().GetCommonSettings()->m_Git, wxGetUserName() );
142
143 {
144 DIALOG_GIT_IDENTITY dlg( aParent, _( "Set Author" ), config.authorName, config.authorEmail );
145
146 if( dlg.ShowModal() != wxID_OK )
147 return false;
148
149 config.authorName = dlg.GetName();
150 config.authorEmail = dlg.GetEmail();
151 }
152
153 if( !parent || parent->IsBeingDeleted() || !identitySessionCurrent( frame.get(), aCommon ) )
154 return false;
155
156 bool saved = false;
157
158 {
159 std::unique_lock<std::mutex> lock = KIGIT::TryLockAction( *aCommon, aParent );
160
161 if( !lock.owns_lock() )
162 return false;
163
164 if( !identitySessionCurrent( frame.get(), aCommon ) )
165 return false;
166
167 saved = aCommon->SetUserConfig( config.authorName, config.authorEmail );
168 }
169
170 if( !saved )
171 {
172 DisplayErrorMessage( aParent, _( "Could not save the name and email to the repository." ) );
173 return false;
174 }
175
176 aCommon->NotifyRefreshListeners();
177 return true;
178}
179
180
181bool KIGIT::EnsureGitIdentity( wxWindow* aParent, EDA_BASE_FRAME* aFrame, const std::shared_ptr<KIGIT_COMMON>& aCommon,
182 const GIT_IDENTITY& aIdentity )
183{
184 if( !identitySessionCurrent( aFrame, aCommon ) )
185 return false;
186
187 return aIdentity.configured || EditGitIdentity( aParent, aFrame, aCommon, aIdentity );
188}
KIGIT_COMMON::GIT_CONN_TYPE GetConnType() const
Ask for the name and email to record commits with.
wxString GetName() const
wxString GetEmail() const
int ShowModal() override
The base frame for deriving all KiCad main window classes.
virtual bool GetConfigString(GIT_CONFIG_HANDLER *aHandler, const wxString &aKey, wxString &aValue)=0
The project's git session.
GIT_CONN_TYPE GetConnType() const
wxString GetRemote() const
wxString GetSSHKey() const
The key this session prefers, which is the one the project was set up with.
void SetSSHKey(const wxString &aSSHKey)
void SetUsername(const wxString &aUsername)
git_repository * GetRepo() const
wxString GetUsername() const
std::atomic< unsigned > & TestedTypes()
void SetPassword(const wxString &aPassword)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:550
bool m_GitIntegrationDisabled
If true, KiCad will not use Git integration for this project even if a .git directory exists.
Container for project specific data.
Definition project.h:63
virtual std::shared_ptr< KIGIT_COMMON > GetGitCommon() const
This project's Git session, created empty on first use.
Definition project.cpp:84
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:207
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define _(s)
Base window classes and related definitions.
GIT_BACKEND * GetGitBackend()
GitUserConfig ResolveGitIdentity(const GIT_IDENTITY &aIdentity, const COMMON_SETTINGS::GIT &aPreferences, const wxString &aUserName)
Fill missing values from custom preferences, then use the OS user name if needed.
GIT_IDENTITY ReadGitIdentity(KIGIT_COMMON &aCommon)
Read on a worker while holding the session's action lock.
bool EnsureGitIdentity(wxWindow *aParent, EDA_BASE_FRAME *aFrame, const std::shared_ptr< KIGIT_COMMON > &aCommon, const GIT_IDENTITY &aIdentity)
Open the same editor when the worker snapshot has no usable Git identity.
bool PromptForCredentials(wxWindow *aParent, KIGIT_COMMON *aCommon, PROJECT *aProject=nullptr)
Ask the user for the credentials of the session's remote and apply them to the session.
std::unique_lock< std::mutex > TryLockAction(KIGIT_COMMON &aCommon, wxWindow *aParent)
Try the action lock and show a busy message if it is unavailable.
bool EditGitIdentity(wxWindow *aParent, EDA_BASE_FRAME *aFrame, const std::shared_ptr< KIGIT_COMMON > &aCommon, const GIT_IDENTITY &aIdentity)
Edit the repository's author and refresh Git views after saving.
std::unique_ptr< git_signature, decltype([](git_signature *aSignature) { git_signature_free(aSignature); })> GitSignaturePtr
A unique pointer for git_signature objects with automatic cleanup.
bool StoreSecret(const wxString &aService, const wxString &aKey, const wxString &aSecret)
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Repository values and whether Git can use them to record a commit.