Skip to content

Commit 1b25a3d

Browse files
authored
Merge pull request #803 from FastReports/sync_branch_2026.1.4
FastReport.OpenSource 2026.1.4
2 parents 7ccdb4a + e916297 commit 1b25a3d

57 files changed

Lines changed: 2928 additions & 57 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Extras/Core/FastReport.Data/Connections.props

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<Project>
1+
<Project>
22
<PropertyGroup>
33
<RootNamespace>FastReport.Data</RootNamespace>
44

5-
<Copyright>Fast Reports Inc.</Copyright>
5+
<Copyright>Copyright © Fast Reports Inc. 2007-2026</Copyright>
66
<Company>Fast Reports Inc.</Company>
77
<Authors>Fast Reports Inc.</Authors>
88

@@ -15,6 +15,11 @@
1515

1616
</PropertyGroup>
1717

18+
<PropertyGroup Condition="'$(Configuration)'!='Debug'">
19+
<DebugSymbols>false</DebugSymbols>
20+
<DebugType>none</DebugType>
21+
</PropertyGroup>
22+
1823
<PropertyGroup Condition="$(Crossplatform)=='true'">
1924
<DefineConstants>$(DefineConstants);FRCORE</DefineConstants>
2025
</PropertyGroup>

Extras/Core/FastReport.Data/FastReport.Data.Excel/Shared.props

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99

1010
<ItemGroup>
1111
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
12-
<PackageReference Include="SpreadsheetLight" Version="3.5.0" />
13-
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
12+
<PackageReference Include="SpreadsheetLight" Version="3.5.0">
13+
<PrivateAssets>compile</PrivateAssets>
14+
</PackageReference>
1415
</ItemGroup>
1516

1617
<ItemGroup>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using FastReport.Utils;
2+
3+
namespace FastReport.Data
4+
{
5+
public class GoogleSheetsAssemblyInitializer : AssemblyInitializerBase
6+
{
7+
public GoogleSheetsAssemblyInitializer()
8+
{
9+
RegisteredObjects.AddConnection(typeof(GoogleSheetsDataConnection));
10+
}
11+
}
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>$(NetFrameworkMinimum);net6.0</TargetFrameworks>
4+
<Crossplatform>true</Crossplatform>
5+
</PropertyGroup>
6+
7+
<Import Project="Shared.props" />
8+
9+
<ItemGroup>
10+
<PackageReference Include="System.Text.Json" Version="8.0.6" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="..\..\..\..\FastReport.OpenSource\FastReport.OpenSource.csproj" />
15+
</ItemGroup>
16+
</Project>
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#if !FRCORE
2+
using FastReport.Forms;
3+
using FastReport.Utils;
4+
using System;
5+
using System.Windows.Forms;
6+
7+
namespace FastReport.Data
8+
{
9+
/// <summary>
10+
/// A dialog form that allows the user to configure authentication settings
11+
/// (OAuth 2.0 or API Key) for connecting to Google services.
12+
/// </summary>
13+
internal partial class GoogleAuthConfigurationDialog : BaseDialogForm
14+
{
15+
#region Constructors
16+
17+
/// <summary>
18+
/// Initializes a new instance of the GoogleAuthConfigurationDialog.
19+
/// </summary>
20+
public GoogleAuthConfigurationDialog()
21+
{
22+
InitializeComponent();
23+
Localize();
24+
InitAuthModes(); // sets up the authentication mode selector (OAuth/API Key)
25+
LoadStoredSettings(); // loads and applies previously saved settings
26+
UIUtils.CheckRTL(this);
27+
UpdateDpiDependencies();
28+
}
29+
30+
#endregion
31+
32+
#region Events Handlers
33+
34+
private void tbPathToJsonFile_ButtonClick(object sender, EventArgs e)
35+
{
36+
using (OpenFileDialog dialog = new OpenFileDialog())
37+
{
38+
dialog.Filter = Res.Get("FileFilters,JsonFile");
39+
if (dialog.ShowDialog() == DialogResult.OK)
40+
tbPathToJsonFile.Text = dialog.FileName;
41+
}
42+
}
43+
44+
private void cbxPathToJsonFile_CheckedChanged(object sender, EventArgs e)
45+
{
46+
bool useJsonFile = cbxPathToJsonFile.Checked;
47+
48+
lblPathToJsonFile.Visible = useJsonFile;
49+
tbPathToJsonFile.Visible = useJsonFile;
50+
51+
lblClientId.Visible = !useJsonFile;
52+
tbClientId.Visible = !useJsonFile;
53+
lblClientSecret.Visible = !useJsonFile;
54+
tbClientSecret.Visible = !useJsonFile;
55+
56+
ResetData();
57+
}
58+
59+
private void btnOk_Click(object sender, EventArgs e)
60+
{
61+
if (string.IsNullOrEmpty(tbClientId.Text) && string.IsNullOrEmpty(tbClientSecret.Text)
62+
&& string.IsNullOrEmpty(tbPathToJsonFile.Text)
63+
&& string.IsNullOrEmpty(tbApiKey.Text))
64+
{
65+
MessageBox.Show(Res.Get("ConnectionEditors,GoogleSheets,SignInGoogle,NullData"));
66+
}
67+
else
68+
{
69+
XmlItem storageSettings = Config.Root.FindItem("GoogleSheets").FindItem("StorageSettings");
70+
71+
storageSettings.SetProp("ClientId", Crypter.EncryptString(tbClientId.Text));
72+
storageSettings.SetProp("ClientSecret", Crypter.EncryptString(tbClientSecret.Text));
73+
storageSettings.SetProp("PathToJson", tbPathToJsonFile.Text); // path is not a secret, no need to encrypt
74+
storageSettings.SetProp("ApiKey", Crypter.EncryptString(tbApiKey.Text));
75+
76+
DialogResult = DialogResult.OK;
77+
Close();
78+
}
79+
}
80+
81+
private void cbxAuthMode_SelectedIndexChanged(object sender, EventArgs e)
82+
{
83+
bool isOAuth = (cbxAuthMode.SelectedIndex == 0);
84+
85+
gbxOAuth.Visible = isOAuth;
86+
gbxOAuth.Enabled = isOAuth;
87+
88+
gbxApiKey.Visible = !isOAuth;
89+
gbxApiKey.Enabled = !isOAuth;
90+
91+
ResetData();
92+
}
93+
94+
#endregion
95+
96+
#region Private Methods
97+
98+
/// <summary>
99+
/// Loads saved authentication settings from the configuration and updates the UI.
100+
/// Determines the authentication mode based on the saved data and populates the relevant fields.
101+
/// </summary>
102+
private void LoadStoredSettings()
103+
{
104+
XmlItem xi = Config.Root.FindItem("GoogleSheets").FindItem("StorageSettings");
105+
if (xi == null)
106+
return;
107+
108+
string clientId = Crypter.DecryptString(xi.GetProp("ClientId"));
109+
string clientSecret = Crypter.DecryptString(xi.GetProp("ClientSecret"));
110+
string pathToJson = xi.GetProp("PathToJson");
111+
string apiKey = Crypter.DecryptString(xi.GetProp("ApiKey"));
112+
113+
if (!string.IsNullOrEmpty(apiKey))
114+
{
115+
// API Key mode was used
116+
cbxAuthMode.SelectedIndex = 1;
117+
tbApiKey.Text = apiKey;
118+
}
119+
else
120+
{
121+
// OAuth 2.0 mode was used
122+
cbxAuthMode.SelectedIndex = 0;
123+
if (!string.IsNullOrEmpty(pathToJson))
124+
{
125+
// JSON file path was used
126+
cbxPathToJsonFile.Checked = true;
127+
tbPathToJsonFile.Text = pathToJson;
128+
}
129+
else
130+
{
131+
// Client ID/ Secret were used
132+
cbxPathToJsonFile.Checked = false;
133+
tbClientId.Text = clientId;
134+
tbClientSecret.Text = clientSecret;
135+
}
136+
}
137+
}
138+
139+
/// <summary>
140+
/// Initializes the authentication mode selector with available options (OAuth 2.0, API key).
141+
/// </summary>
142+
private void InitAuthModes()
143+
{
144+
cbxAuthMode.Items.Add("OAuth 2.0");
145+
cbxAuthMode.Items.Add("API key");
146+
cbxAuthMode.SelectedIndex = 0;
147+
}
148+
149+
/// <summary>
150+
/// Clears input fields that are hidden when switching authentication modes.
151+
/// </summary>
152+
private void ResetData()
153+
{
154+
if (cbxAuthMode.SelectedIndex == 0) // OAuth mode
155+
{
156+
tbApiKey.Text = "";
157+
158+
if (cbxPathToJsonFile.Checked)
159+
{
160+
tbClientId.Text = "";
161+
tbClientSecret.Text = "";
162+
}
163+
else
164+
{
165+
tbPathToJsonFile.Text = "";
166+
}
167+
}
168+
else // API Key mode
169+
{
170+
tbClientId.Text = "";
171+
tbClientSecret.Text = "";
172+
tbPathToJsonFile.Text = "";
173+
}
174+
}
175+
176+
#endregion
177+
178+
#region Public Methods
179+
180+
/// <inheritdoc/>
181+
public override void Localize()
182+
{
183+
base.Localize();
184+
MyRes res = new MyRes("ConnectionEditors,GoogleSheets,SignInGoogle");
185+
186+
Text = res.Get("");
187+
lblCaption.Text = res.Get("Caption");
188+
lblClientId.Text = res.Get("ClientId");
189+
lblClientSecret.Text = res.Get("ClientSecret");
190+
lblPathToJsonFile.Text = res.Get("PathToFile");
191+
lblApiKey.Text = res.Get("ApiKey");
192+
cbxPathToJsonFile.Text = res.Get("CheckPathToJson");
193+
}
194+
195+
/// <inheritdoc/>
196+
public override void UpdateDpiDependencies()
197+
{
198+
base.UpdateDpiDependencies();
199+
tbPathToJsonFile.Image = this.GetImage(1);
200+
}
201+
202+
#endregion
203+
}
204+
}
205+
#endif

0 commit comments

Comments
 (0)