Skip to content

Commit 628fd7b

Browse files
committed
Primary resource impl CC
1 parent cefeec7 commit 628fd7b

File tree

7 files changed

+331
-1
lines changed

7 files changed

+331
-1
lines changed

src/AppInstallerCLICore/AppInstallerCLICore.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@
302302
<ClInclude Include="Commands\ConfigureValidateCommand.h" />
303303
<ClInclude Include="Commands\DebugCommand.h" />
304304
<ClInclude Include="Commands\DownloadCommand.h" />
305+
<ClInclude Include="Commands\DscAdminSettingsResource.h" />
305306
<ClInclude Include="Commands\DscCommand.h" />
306307
<ClInclude Include="Commands\DscCommandBase.h" />
307308
<ClInclude Include="Commands\DscComposableObject.h" />
@@ -390,6 +391,7 @@
390391
<ClCompile Include="Commands\ConfigureValidateCommand.cpp" />
391392
<ClCompile Include="Commands\DebugCommand.cpp" />
392393
<ClCompile Include="Commands\DownloadCommand.cpp" />
394+
<ClCompile Include="Commands\DscAdminSettingsResource.cpp" />
393395
<ClCompile Include="Commands\DscCommand.cpp" />
394396
<ClCompile Include="Commands\DscCommandBase.cpp" />
395397
<ClCompile Include="Commands\DscComposableObject.cpp" />

src/AppInstallerCLICore/AppInstallerCLICore.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@
290290
<ClInclude Include="Commands\DscUserSettingsFileResource.h">
291291
<Filter>Commands\Configuration</Filter>
292292
</ClInclude>
293+
<ClInclude Include="Commands\DscAdminSettingsResource.h">
294+
<Filter>Commands\Configuration</Filter>
295+
</ClInclude>
293296
</ItemGroup>
294297
<ItemGroup>
295298
<ClCompile Include="pch.cpp">
@@ -547,6 +550,9 @@
547550
<ClCompile Include="Commands\DscUserSettingsFileResource.cpp">
548551
<Filter>Commands\Configuration</Filter>
549552
</ClCompile>
553+
<ClCompile Include="Commands\DscAdminSettingsResource.cpp">
554+
<Filter>Commands\Configuration</Filter>
555+
</ClCompile>
550556
</ItemGroup>
551557
<ItemGroup>
552558
<None Include="PropertySheet.props" />
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
#include "pch.h"
4+
#include "DscAdminSettingsResource.h"
5+
#include "DscComposableObject.h"
6+
#include "Resources.h"
7+
#include <winget/AdminSettings.h>
8+
9+
using namespace AppInstaller::Utility::literals;
10+
using namespace AppInstaller::Repository;
11+
12+
namespace AppInstaller::CLI
13+
{
14+
namespace AdminSettingsDetails
15+
{
16+
// The base for admin settings.
17+
struct IAdminSetting
18+
{
19+
virtual ~IAdminSetting() = default;
20+
21+
// Gets the name of the setting.
22+
virtual Utility::LocIndView SettingName() const = 0;
23+
24+
// Tests the value.
25+
// Returns true if in the deired state; false if not.
26+
virtual bool Test() const = 0;
27+
28+
// Sets the value.
29+
// Returns true if the value could be set; false if not.
30+
virtual bool Set() const = 0;
31+
};
32+
33+
// A boolean based admin setting
34+
struct AdminSetting_Bool : public IAdminSetting
35+
{
36+
AdminSetting_Bool(Settings::BoolAdminSetting setting, bool value) : m_setting(setting), m_value(value) {}
37+
38+
Utility::LocIndView SettingName() const override
39+
{
40+
return Settings::AdminSettingToString(m_setting);
41+
}
42+
43+
bool Test() const override
44+
{
45+
return Settings::IsAdminSettingEnabled(m_setting) == m_value;
46+
}
47+
48+
bool Set() const override
49+
{
50+
return m_value ? Settings::EnableAdminSetting(m_setting) : Settings::DisableAdminSetting(m_setting);
51+
}
52+
53+
private:
54+
Settings::BoolAdminSetting m_setting;
55+
bool m_value;
56+
};
57+
58+
// A string based admin setting
59+
struct AdminSetting_String : public IAdminSetting
60+
{
61+
AdminSetting_String(Settings::StringAdminSetting setting, std::optional<std::string> value) : m_setting(setting), m_value(std::move(value)) {}
62+
63+
Utility::LocIndView SettingName() const override
64+
{
65+
return Settings::AdminSettingToString(m_setting);
66+
}
67+
68+
bool Test() const override
69+
{
70+
return Settings::GetAdminSetting(m_setting) == m_value;
71+
}
72+
73+
bool Set() const override
74+
{
75+
return m_value ? Settings::SetAdminSetting(m_setting, m_value.value()) : Settings::ResetAdminSetting(m_setting);
76+
}
77+
78+
private:
79+
Settings::StringAdminSetting m_setting;
80+
std::optional<std::string> m_value;
81+
};
82+
}
83+
84+
namespace
85+
{
86+
WINGET_DSC_DEFINE_COMPOSABLE_PROPERTY(SettingsProperty, Json::Value, Settings, "settings", Resource::String::DscResourcePropertyDescriptionAdminSettingsSettings);
87+
88+
using AdminSettingsResourceObject = DscComposableObject<StandardInDesiredStateProperty, SettingsProperty>;
89+
90+
struct AdminSettingsFunctionData
91+
{
92+
AdminSettingsFunctionData() = default;
93+
94+
AdminSettingsFunctionData(const std::optional<Json::Value>& json) :
95+
Input(json)
96+
{
97+
}
98+
99+
const AdminSettingsResourceObject Input;
100+
AdminSettingsResourceObject Output;
101+
std::vector<std::unique_ptr<AdminSettingsDetails::IAdminSetting>> InputSettings;
102+
103+
// Converts the input settings into the appropriate settings object.
104+
void ParseSettings()
105+
{
106+
if (Input.Settings())
107+
{
108+
const Json::Value& inputSettings = Input.Settings().value();
109+
for (const auto& property : inputSettings.getMemberNames())
110+
{
111+
auto boolSetting = Settings::StringToBoolAdminSetting(property);
112+
if (boolSetting != Settings::BoolAdminSetting::Unknown)
113+
{
114+
bool value = inputSettings[property].asBool();
115+
AICLI_LOG(Config, Info, << "Bool admin setting: " << property << " => " << (value ? "true" : "false"));
116+
InputSettings.emplace_back(std::make_unique<AdminSettingsDetails::AdminSetting_Bool>(boolSetting, value));
117+
continue;
118+
}
119+
120+
auto stringSetting = Settings::StringToStringAdminSetting(property);
121+
if (stringSetting != Settings::StringAdminSetting::Unknown)
122+
{
123+
std::string value = inputSettings[property].asString();
124+
AICLI_LOG(Config, Info, << "String admin setting: " << property << " => " << value);
125+
InputSettings.emplace_back(std::make_unique<AdminSettingsDetails::AdminSetting_String>(stringSetting, value));
126+
continue;
127+
}
128+
129+
AICLI_LOG(Config, Warning, << "Unknown admin setting: " << property);
130+
}
131+
}
132+
}
133+
134+
// Fills the Output object with the current state
135+
void Get()
136+
{
137+
Json::Value adminSettings{ Json::objectValue };
138+
139+
for (const auto& setting : Settings::GetAllBoolAdminSettings())
140+
{
141+
auto str = std::string{ Settings::AdminSettingToString(setting) };
142+
adminSettings[str] = Settings::IsAdminSettingEnabled(setting);
143+
}
144+
145+
for (const auto& setting : Settings::GetAllStringAdminSettings())
146+
{
147+
auto name = std::string{ Settings::AdminSettingToString(setting) };
148+
auto value = Settings::GetAdminSetting(setting);
149+
if (value)
150+
{
151+
adminSettings[name] = value.value();
152+
}
153+
}
154+
155+
Output.Settings(std::move(adminSettings));
156+
}
157+
158+
// Determines if the current Output values match the Input values state.
159+
bool Test()
160+
{
161+
for (const auto& setting : InputSettings)
162+
{
163+
if (!setting->Test())
164+
{
165+
return false;
166+
}
167+
}
168+
169+
return true;
170+
}
171+
172+
// Sets all of the input settings.
173+
void Set()
174+
{
175+
for (const auto& setting : InputSettings)
176+
{
177+
if (!setting->Test())
178+
{
179+
if (!setting->Set())
180+
{
181+
auto message = Resource::String::DisabledByGroupPolicy(setting->SettingName());
182+
THROW_HR_MSG(APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY, "%hs", message.get().c_str());
183+
}
184+
}
185+
}
186+
}
187+
188+
Json::Value DiffJson(bool inDesiredState)
189+
{
190+
Json::Value result{ Json::ValueType::arrayValue };
191+
192+
if (!inDesiredState)
193+
{
194+
result.append(std::string{ SettingsProperty::Name() });
195+
}
196+
197+
return result;
198+
}
199+
};
200+
}
201+
202+
DscAdminSettingsResource::DscAdminSettingsResource(std::string_view parent) :
203+
DscCommandBase(parent, "admin-settings", DscResourceKind::Resource,
204+
DscFunctions::Get | DscFunctions::Set | DscFunctions::Test | DscFunctions::Export | DscFunctions::Schema,
205+
DscFunctionModifiers::ImplementsPretest | DscFunctionModifiers::ReturnsStateAndDiff)
206+
{
207+
}
208+
209+
Resource::LocString DscAdminSettingsResource::ShortDescription() const
210+
{
211+
return Resource::String::DscAdminSettingsResourceShortDescription;
212+
}
213+
214+
Resource::LocString DscAdminSettingsResource::LongDescription() const
215+
{
216+
return Resource::String::DscAdminSettingsResourceLongDescription;
217+
}
218+
219+
std::string DscAdminSettingsResource::ResourceType() const
220+
{
221+
return "AdminSettings";
222+
}
223+
224+
void DscAdminSettingsResource::ResourceFunctionGet(Execution::Context& context) const
225+
{
226+
AdminSettingsFunctionData data;
227+
data.Get();
228+
WriteJsonOutputLine(context, data.Output.ToJson());
229+
}
230+
231+
void DscAdminSettingsResource::ResourceFunctionSet(Execution::Context& context) const
232+
{
233+
if (auto json = GetJsonFromInput(context))
234+
{
235+
AdminSettingsFunctionData data{ json };
236+
237+
data.ParseSettings();
238+
239+
bool inDesiredState = data.Test();
240+
if (!inDesiredState)
241+
{
242+
Workflow::EnsureRunningAsAdmin(context);
243+
244+
if (context.IsTerminated())
245+
{
246+
return;
247+
}
248+
249+
data.Set();
250+
}
251+
252+
data.Get();
253+
WriteJsonOutputLine(context, data.Output.ToJson());
254+
WriteJsonOutputLine(context, data.DiffJson(inDesiredState));
255+
}
256+
}
257+
258+
void DscAdminSettingsResource::ResourceFunctionTest(Execution::Context& context) const
259+
{
260+
if (auto json = GetJsonFromInput(context))
261+
{
262+
AdminSettingsFunctionData data{ json };
263+
264+
data.ParseSettings();
265+
266+
data.Get();
267+
data.Output.InDesiredState(data.Test());
268+
269+
WriteJsonOutputLine(context, data.Output.ToJson());
270+
WriteJsonOutputLine(context, data.DiffJson(data.Output.InDesiredState().value()));
271+
}
272+
}
273+
274+
void DscAdminSettingsResource::ResourceFunctionExport(Execution::Context& context) const
275+
{
276+
ResourceFunctionGet(context);
277+
}
278+
279+
void DscAdminSettingsResource::ResourceFunctionSchema(Execution::Context& context) const
280+
{
281+
WriteJsonOutputLine(context, AdminSettingsResourceObject::Schema(ResourceType()));
282+
}
283+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
#pragma once
4+
#include "DscCommandBase.h"
5+
6+
namespace AppInstaller::CLI
7+
{
8+
// A resource for managing source configuration.
9+
struct DscAdminSettingsResource : public DscCommandBase
10+
{
11+
DscAdminSettingsResource(std::string_view parent);
12+
13+
Resource::LocString ShortDescription() const override;
14+
Resource::LocString LongDescription() const override;
15+
16+
protected:
17+
std::string ResourceType() const override;
18+
19+
void ResourceFunctionGet(Execution::Context& context) const override;
20+
void ResourceFunctionSet(Execution::Context& context) const override;
21+
void ResourceFunctionTest(Execution::Context& context) const override;
22+
void ResourceFunctionExport(Execution::Context& context) const override;
23+
void ResourceFunctionSchema(Execution::Context& context) const override;
24+
};
25+
}

src/AppInstallerCLICore/Commands/DscCommand.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "DscPackageResource.h"
66
#include "DscUserSettingsFileResource.h"
77
#include "DscSourceResource.h"
8+
#include "DscAdminSettingsResource.h"
89

910
#ifndef AICLI_DISABLE_TEST_HOOKS
1011
#include "DscTestFileResource.h"
@@ -33,6 +34,7 @@ namespace AppInstaller::CLI
3334
std::make_unique<DscPackageResource>(FullName()),
3435
std::make_unique<DscSourceResource>(FullName()),
3536
std::make_unique<DscUserSettingsFileResource>(FullName()),
37+
std::make_unique<DscAdminSettingsResource>(FullName()),
3638
#ifndef AICLI_DISABLE_TEST_HOOKS
3739
std::make_unique<DscTestFileResource>(FullName()),
3840
std::make_unique<DscTestJsonResource>(FullName()),

src/AppInstallerCLICore/Resources.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ namespace AppInstaller::CLI::Resource
223223
WINGET_DEFINE_RESOURCE_STRINGID(Downloading);
224224
WINGET_DEFINE_RESOURCE_STRINGID(DscCommandLongDescription);
225225
WINGET_DEFINE_RESOURCE_STRINGID(DscCommandShortDescription);
226+
WINGET_DEFINE_RESOURCE_STRINGID(DscAdminSettingsResourceShortDescription);
227+
WINGET_DEFINE_RESOURCE_STRINGID(DscAdminSettingsResourceLongDescription);
226228
WINGET_DEFINE_RESOURCE_STRINGID(DscPackageResourceShortDescription);
227229
WINGET_DEFINE_RESOURCE_STRINGID(DscPackageResourceLongDescription);
228230
WINGET_DEFINE_RESOURCE_STRINGID(DscResourceFunctionDescriptionGet);
@@ -239,6 +241,7 @@ namespace AppInstaller::CLI::Resource
239241
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionExist);
240242
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionInDesiredState);
241243
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionAcceptAgreements);
244+
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionAdminSettingsSettings);
242245
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionPackageId);
243246
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionPackageSource);
244247
WINGET_DEFINE_RESOURCE_STRINGID(DscResourcePropertyDescriptionPackageVersion);

src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3355,4 +3355,13 @@ Please specify one of them using the --source option to proceed.</value>
33553355
<value>Failed to install Desired State Configuration package. Install the package manually or provide the path to dsc.exe through --processor-path argument.</value>
33563356
<comment>{Locked="dsc.exe","--processor-path"}</comment>
33573357
</data>
3358-
</root>
3358+
<data name="DscResourcePropertyDescriptionAdminSettingsSettings" xml:space="preserve">
3359+
<value>An object containing the administrator settings and their values.</value>
3360+
</data>
3361+
<data name="DscAdminSettingsResourceShortDescription" xml:space="preserve">
3362+
<value>Manage administrator settings</value>
3363+
</data>
3364+
<data name="DscAdminSettingsResourceLongDescription" xml:space="preserve">
3365+
<value>Allows management of administrator settings the DSC v3 command line interface protocol. See the help link for details.</value>
3366+
</data>
3367+
</root>

0 commit comments

Comments
 (0)