mirror of https://github.com/coder/coder.git
bep
This commit is contained in:
parent
215dd7b152
commit
f432099664
|
@ -8280,6 +8280,9 @@ const docTemplate = `{
|
|||
"items": {
|
||||
"$ref": "#/definitions/codersdk.LinkConfig"
|
||||
}
|
||||
},
|
||||
"terms_of_service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -11896,6 +11899,9 @@ const docTemplate = `{
|
|||
},
|
||||
"service_banner": {
|
||||
"$ref": "#/definitions/codersdk.ServiceBannerConfig"
|
||||
},
|
||||
"terms_of_service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7349,6 +7349,9 @@
|
|||
"items": {
|
||||
"$ref": "#/definitions/codersdk.LinkConfig"
|
||||
}
|
||||
},
|
||||
"terms_of_service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -10755,6 +10758,9 @@
|
|||
},
|
||||
"service_banner": {
|
||||
"$ref": "#/definitions/codersdk.ServiceBannerConfig"
|
||||
},
|
||||
"terms_of_service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1793,6 +1793,11 @@ func (q *querier) GetTemplatesWithFilter(ctx context.Context, arg database.GetTe
|
|||
return q.db.GetAuthorizedTemplates(ctx, arg, prep)
|
||||
}
|
||||
|
||||
func (q *querier) GetTermsOfService(ctx context.Context) (string, error) {
|
||||
// No authz checks
|
||||
return q.db.GetTermsOfService(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetUnexpiredLicenses(ctx context.Context) ([]database.License, error) {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return nil, err
|
||||
|
@ -3438,6 +3443,13 @@ func (q *querier) UpsertTemplateUsageStats(ctx context.Context) error {
|
|||
return q.db.UpsertTemplateUsageStats(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertTermsOfService(ctx context.Context, value string) error {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceDeploymentValues); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertTermsOfService(ctx, value)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertWorkspaceAgentPortShare(ctx context.Context, arg database.UpsertWorkspaceAgentPortShareParams) (database.WorkspaceAgentPortShare, error) {
|
||||
workspace, err := q.db.GetWorkspaceByID(ctx, arg.WorkspaceID)
|
||||
if err != nil {
|
||||
|
|
|
@ -4213,6 +4213,10 @@ func (q *FakeQuerier) GetTemplatesWithFilter(ctx context.Context, arg database.G
|
|||
return q.GetAuthorizedTemplates(ctx, arg, nil)
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetTermsOfService(ctx context.Context) (string, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetUnexpiredLicenses(_ context.Context) ([]database.License, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
@ -8932,6 +8936,10 @@ TemplateUsageStatsInsertLoop:
|
|||
return nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpsertTermsOfService(ctx context.Context, value string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpsertWorkspaceAgentPortShare(_ context.Context, arg database.UpsertWorkspaceAgentPortShareParams) (database.WorkspaceAgentPortShare, error) {
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
|
|
|
@ -1038,6 +1038,13 @@ func (m metricsStore) GetTemplatesWithFilter(ctx context.Context, arg database.G
|
|||
return templates, err
|
||||
}
|
||||
|
||||
func (m metricsStore) GetTermsOfService(ctx context.Context) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetTermsOfService(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetTermsOfService").Observe(time.Since(start).Seconds())
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m metricsStore) GetUnexpiredLicenses(ctx context.Context) ([]database.License, error) {
|
||||
start := time.Now()
|
||||
licenses, err := m.s.GetUnexpiredLicenses(ctx)
|
||||
|
@ -2256,6 +2263,13 @@ func (m metricsStore) UpsertTemplateUsageStats(ctx context.Context) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpsertTermsOfService(ctx context.Context, value string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertTermsOfService(ctx, value)
|
||||
m.queryLatencies.WithLabelValues("UpsertTermsOfService").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpsertWorkspaceAgentPortShare(ctx context.Context, arg database.UpsertWorkspaceAgentPortShareParams) (database.WorkspaceAgentPortShare, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.UpsertWorkspaceAgentPortShare(ctx, arg)
|
||||
|
|
|
@ -2145,6 +2145,21 @@ func (mr *MockStoreMockRecorder) GetTemplatesWithFilter(arg0, arg1 any) *gomock.
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTemplatesWithFilter", reflect.TypeOf((*MockStore)(nil).GetTemplatesWithFilter), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetTermsOfService mocks base method.
|
||||
func (m *MockStore) GetTermsOfService(arg0 context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetTermsOfService", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetTermsOfService indicates an expected call of GetTermsOfService.
|
||||
func (mr *MockStoreMockRecorder) GetTermsOfService(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTermsOfService", reflect.TypeOf((*MockStore)(nil).GetTermsOfService), arg0)
|
||||
}
|
||||
|
||||
// GetUnexpiredLicenses mocks base method.
|
||||
func (m *MockStore) GetUnexpiredLicenses(arg0 context.Context) ([]database.License, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -4723,6 +4738,20 @@ func (mr *MockStoreMockRecorder) UpsertTemplateUsageStats(arg0 any) *gomock.Call
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertTemplateUsageStats", reflect.TypeOf((*MockStore)(nil).UpsertTemplateUsageStats), arg0)
|
||||
}
|
||||
|
||||
// UpsertTermsOfService mocks base method.
|
||||
func (m *MockStore) UpsertTermsOfService(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertTermsOfService", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertTermsOfService indicates an expected call of UpsertTermsOfService.
|
||||
func (mr *MockStoreMockRecorder) UpsertTermsOfService(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertTermsOfService", reflect.TypeOf((*MockStore)(nil).UpsertTermsOfService), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpsertWorkspaceAgentPortShare mocks base method.
|
||||
func (m *MockStore) UpsertWorkspaceAgentPortShare(arg0 context.Context, arg1 database.UpsertWorkspaceAgentPortShareParams) (database.WorkspaceAgentPortShare, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
@ -215,6 +215,7 @@ type sqlcQuerier interface {
|
|||
GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error)
|
||||
GetTemplates(ctx context.Context) ([]Template, error)
|
||||
GetTemplatesWithFilter(ctx context.Context, arg GetTemplatesWithFilterParams) ([]Template, error)
|
||||
GetTermsOfService(ctx context.Context) (string, error)
|
||||
GetUnexpiredLicenses(ctx context.Context) ([]License, error)
|
||||
// GetUserActivityInsights returns the ranking with top active users.
|
||||
// The result can be filtered on template_ids, meaning only user data
|
||||
|
@ -435,6 +436,7 @@ type sqlcQuerier interface {
|
|||
// used to store the data, and the minutes are summed for each user and template
|
||||
// combination. The result is stored in the template_usage_stats table.
|
||||
UpsertTemplateUsageStats(ctx context.Context) error
|
||||
UpsertTermsOfService(ctx context.Context, value string) error
|
||||
UpsertWorkspaceAgentPortShare(ctx context.Context, arg UpsertWorkspaceAgentPortShareParams) (WorkspaceAgentPortShare, error)
|
||||
}
|
||||
|
||||
|
|
|
@ -5637,6 +5637,17 @@ func (q *sqlQuerier) GetServiceBanner(ctx context.Context) (string, error) {
|
|||
return value, err
|
||||
}
|
||||
|
||||
const getTermsOfService = `-- name: GetTermsOfService :one
|
||||
SELECT value FROM site_configs WHERE key = 'terms_of_service'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetTermsOfService(ctx context.Context) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getTermsOfService)
|
||||
var value string
|
||||
err := row.Scan(&value)
|
||||
return value, err
|
||||
}
|
||||
|
||||
const insertDERPMeshKey = `-- name: InsertDERPMeshKey :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('derp_mesh_key', $1)
|
||||
`
|
||||
|
@ -5748,6 +5759,16 @@ func (q *sqlQuerier) UpsertServiceBanner(ctx context.Context, value string) erro
|
|||
return err
|
||||
}
|
||||
|
||||
const upsertTermsOfService = `-- name: UpsertTermsOfService :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('terms_of_service', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'terms_of_service'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) UpsertTermsOfService(ctx context.Context, value string) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertTermsOfService, value)
|
||||
return err
|
||||
}
|
||||
|
||||
const cleanTailnetCoordinators = `-- name: CleanTailnetCoordinators :exec
|
||||
DELETE
|
||||
FROM tailnet_coordinators
|
||||
|
|
|
@ -57,6 +57,13 @@ ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'application
|
|||
-- name: GetApplicationName :one
|
||||
SELECT value FROM site_configs WHERE key = 'application_name';
|
||||
|
||||
-- name: UpsertTermsOfService :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('terms_of_service', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'terms_of_service';
|
||||
|
||||
-- name: GetTermsOfService :one
|
||||
SELECT value FROM site_configs WHERE key = 'terms_of_service';
|
||||
|
||||
-- name: GetAppSecurityKey :one
|
||||
SELECT value FROM site_configs WHERE key = 'app_signing_key';
|
||||
|
||||
|
|
|
@ -2078,6 +2078,7 @@ type AppearanceConfig struct {
|
|||
ApplicationName string `json:"application_name"`
|
||||
LogoURL string `json:"logo_url"`
|
||||
ServiceBanner ServiceBannerConfig `json:"service_banner"`
|
||||
TermsOfService string `json:"terms_of_service"`
|
||||
SupportLinks []LinkConfig `json:"support_links,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -2085,6 +2086,7 @@ type UpdateAppearanceConfig struct {
|
|||
ApplicationName string `json:"application_name"`
|
||||
LogoURL string `json:"logo_url"`
|
||||
ServiceBanner ServiceBannerConfig `json:"service_banner"`
|
||||
TermsOfService string `json:"terms_of_service"`
|
||||
}
|
||||
|
||||
type ServiceBannerConfig struct {
|
||||
|
|
|
@ -32,7 +32,8 @@ curl -X GET http://coder-server:8080/api/v2/appearance \
|
|||
"name": "string",
|
||||
"target": "string"
|
||||
}
|
||||
]
|
||||
],
|
||||
"terms_of_service": "string"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -68,7 +69,8 @@ curl -X PUT http://coder-server:8080/api/v2/appearance \
|
|||
"background_color": "string",
|
||||
"enabled": true,
|
||||
"message": "string"
|
||||
}
|
||||
},
|
||||
"terms_of_service": "string"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -90,7 +92,8 @@ curl -X PUT http://coder-server:8080/api/v2/appearance \
|
|||
"background_color": "string",
|
||||
"enabled": true,
|
||||
"message": "string"
|
||||
}
|
||||
},
|
||||
"terms_of_service": "string"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -762,7 +762,8 @@
|
|||
"name": "string",
|
||||
"target": "string"
|
||||
}
|
||||
]
|
||||
],
|
||||
"terms_of_service": "string"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -774,6 +775,7 @@
|
|||
| `logo_url` | string | false | | |
|
||||
| `service_banner` | [codersdk.ServiceBannerConfig](#codersdkservicebannerconfig) | false | | |
|
||||
| `support_links` | array of [codersdk.LinkConfig](#codersdklinkconfig) | false | | |
|
||||
| `terms_of_service` | string | false | | |
|
||||
|
||||
## codersdk.ArchiveTemplateVersionsRequest
|
||||
|
||||
|
@ -5172,7 +5174,8 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
|
|||
"background_color": "string",
|
||||
"enabled": true,
|
||||
"message": "string"
|
||||
}
|
||||
},
|
||||
"terms_of_service": "string"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -5183,6 +5186,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
|
|||
| `application_name` | string | false | | |
|
||||
| `logo_url` | string | false | | |
|
||||
| `service_banner` | [codersdk.ServiceBannerConfig](#codersdkservicebannerconfig) | false | | |
|
||||
| `terms_of_service` | string | false | | |
|
||||
|
||||
## codersdk.UpdateCheckResponse
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ func (f *appearanceFetcher) Fetch(ctx context.Context) (codersdk.AppearanceConfi
|
|||
var applicationName string
|
||||
var logoURL string
|
||||
var serviceBannerJSON string
|
||||
var termsOfService string
|
||||
eg.Go(func() (err error) {
|
||||
applicationName, err = f.database.GetApplicationName(ctx)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
|
@ -77,6 +78,13 @@ func (f *appearanceFetcher) Fetch(ctx context.Context) (codersdk.AppearanceConfi
|
|||
}
|
||||
return nil
|
||||
})
|
||||
eg.Go(func() (err error) {
|
||||
termsOfService, err = f.database.GetTermsOfService(ctx)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return xerrors.Errorf("get terms of service: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
err := eg.Wait()
|
||||
if err != nil {
|
||||
return codersdk.AppearanceConfig{}, err
|
||||
|
@ -85,6 +93,7 @@ func (f *appearanceFetcher) Fetch(ctx context.Context) (codersdk.AppearanceConfi
|
|||
cfg := codersdk.AppearanceConfig{
|
||||
ApplicationName: applicationName,
|
||||
LogoURL: logoURL,
|
||||
TermsOfService: termsOfService,
|
||||
}
|
||||
if serviceBannerJSON != "" {
|
||||
err = json.Unmarshal([]byte(serviceBannerJSON), &cfg.ServiceBanner)
|
||||
|
@ -176,6 +185,15 @@ func (api *API) putAppearance(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
err = api.Database.UpsertTermsOfService(ctx, appearance.TermsOfService)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Unable to set terms of service",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = api.Database.UpsertLogoURL(ctx, appearance.LogoURL)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
|
|
|
@ -1282,6 +1282,8 @@ export const getAppearance = async (): Promise<TypesGen.AppearanceConfig> => {
|
|||
const response = await axios.get(`/api/v2/appearance`);
|
||||
return response.data || {};
|
||||
} catch (ex) {
|
||||
// This endpoint is only available on enterprise binaries. A 404 is expected
|
||||
// from AGPL builds, and should be be treated as a "successful" response.
|
||||
if (axios.isAxiosError(ex) && ex.response?.status === 404) {
|
||||
return {
|
||||
application_name: "",
|
||||
|
@ -1289,6 +1291,7 @@ export const getAppearance = async (): Promise<TypesGen.AppearanceConfig> => {
|
|||
service_banner: {
|
||||
enabled: false,
|
||||
},
|
||||
terms_of_service: "",
|
||||
};
|
||||
}
|
||||
throw ex;
|
||||
|
|
|
@ -49,6 +49,7 @@ export interface AppearanceConfig {
|
|||
readonly application_name: string;
|
||||
readonly logo_url: string;
|
||||
readonly service_banner: ServiceBannerConfig;
|
||||
readonly terms_of_service: string;
|
||||
readonly support_links?: readonly LinkConfig[];
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1280,7 @@ export interface UpdateAppearanceConfig {
|
|||
readonly application_name: string;
|
||||
readonly logo_url: string;
|
||||
readonly service_banner: ServiceBannerConfig;
|
||||
readonly terms_of_service: string;
|
||||
}
|
||||
|
||||
// From codersdk/updatecheck.go
|
||||
|
|
|
@ -22,6 +22,7 @@ const AppearanceSettingsPage: FC = () => {
|
|||
newConfig: Partial<UpdateAppearanceConfig>,
|
||||
preview: boolean,
|
||||
) => {
|
||||
console.log(newConfig);
|
||||
const newAppearance = { ...appearance.config, ...newConfig };
|
||||
if (preview) {
|
||||
appearance.setPreview(newAppearance);
|
||||
|
|
|
@ -13,6 +13,7 @@ const meta: Meta<typeof AppearanceSettingsPageView> = {
|
|||
message: "hello world",
|
||||
background_color: "white",
|
||||
},
|
||||
terms_of_service: "",
|
||||
},
|
||||
isEntitled: false,
|
||||
},
|
||||
|
|
|
@ -80,6 +80,16 @@ export const AppearanceSettingsPageView: FC<
|
|||
serviceBannerForm.values.background_color,
|
||||
);
|
||||
|
||||
const termsOfServiceForm = useFormik<{
|
||||
terms_of_service: string;
|
||||
}>({
|
||||
initialValues: {
|
||||
terms_of_service: appearance.terms_of_service,
|
||||
},
|
||||
onSubmit: (values) => onSaveAppearance(values, false),
|
||||
});
|
||||
const termsOfServiceFieldHelpers = getFormHelpers(termsOfServiceForm);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header
|
||||
|
@ -276,6 +286,30 @@ export const AppearanceSettingsPageView: FC<
|
|||
</Stack>
|
||||
)}
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset
|
||||
title="Terms of Service"
|
||||
subtitle="Add a custom Terms of Service that must be accepted before using Coder."
|
||||
validation={!isEntitled ? "This is an Enterprise only feature." : ""}
|
||||
onSubmit={termsOfServiceForm.handleSubmit}
|
||||
button={!isEntitled && <Button disabled>Submit</Button>}
|
||||
>
|
||||
<TextField
|
||||
{...termsOfServiceFieldHelpers("terms_of_service", {
|
||||
helperText: "Markdown is supported.",
|
||||
})}
|
||||
defaultValue={appearance.terms_of_service}
|
||||
fullWidth
|
||||
multiline
|
||||
label="Terms of Service"
|
||||
placeholder="Leave empty to disable."
|
||||
disabled={!isEntitled}
|
||||
inputProps={{
|
||||
"aria-label": "Terms of Service. Leave empty to disable.",
|
||||
style: { height: 100, resize: "vertical" },
|
||||
}}
|
||||
/>
|
||||
</Fieldset>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ import { useAuthContext } from "contexts/auth/AuthProvider";
|
|||
import { getApplicationName } from "utils/appearance";
|
||||
import { retrieveRedirect } from "utils/redirect";
|
||||
import { LoginPageView } from "./LoginPageView";
|
||||
import { appearance } from "api/queries/appearance";
|
||||
|
||||
export const LoginPage: FC = () => {
|
||||
const location = useLocation();
|
||||
|
@ -24,6 +25,7 @@ export const LoginPage: FC = () => {
|
|||
const applicationName = getApplicationName();
|
||||
const navigate = useNavigate();
|
||||
const buildInfoQuery = useQuery(buildInfo());
|
||||
const siteConfigQuery = useQuery(appearance());
|
||||
|
||||
if (isSignedIn) {
|
||||
// If the redirect is going to a workspace application, and we
|
||||
|
@ -68,6 +70,7 @@ export const LoginPage: FC = () => {
|
|||
error={signInError}
|
||||
isLoading={isLoading || authMethodsQuery.isLoading}
|
||||
buildInfo={buildInfoQuery.data}
|
||||
termsOfService={siteConfigQuery.data?.terms_of_service}
|
||||
isSigningIn={isSigningIn}
|
||||
onSignIn={async ({ email, password }) => {
|
||||
await signIn(email, password);
|
||||
|
|
|
@ -13,6 +13,7 @@ export interface LoginPageViewProps {
|
|||
error: unknown;
|
||||
isLoading: boolean;
|
||||
buildInfo?: BuildInfoResponse;
|
||||
termsOfService?: string;
|
||||
isSigningIn: boolean;
|
||||
onSignIn: (credentials: { email: string; password: string }) => void;
|
||||
}
|
||||
|
@ -22,6 +23,7 @@ export const LoginPageView: FC<LoginPageViewProps> = ({
|
|||
error,
|
||||
isLoading,
|
||||
buildInfo,
|
||||
termsOfService,
|
||||
isSigningIn,
|
||||
onSignIn,
|
||||
}) => {
|
||||
|
@ -49,6 +51,10 @@ export const LoginPageView: FC<LoginPageViewProps> = ({
|
|||
<CoderIcon fill="white" opacity={1} css={styles.icon} />
|
||||
);
|
||||
|
||||
if (termsOfService) {
|
||||
return <>{termsOfService}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div css={styles.root}>
|
||||
<div css={styles.container}>
|
||||
|
|
|
@ -2347,6 +2347,7 @@ export const MockAppearanceConfig: TypesGen.AppearanceConfig = {
|
|||
service_banner: {
|
||||
enabled: false,
|
||||
},
|
||||
terms_of_service: "",
|
||||
};
|
||||
|
||||
export const MockWorkspaceBuildParameter1: TypesGen.WorkspaceBuildParameter = {
|
||||
|
|
Loading…
Reference in New Issue