mirror of
https://github.com/m1k1o/neko-rooms.git
synced 2026-11-02 22:51:34 -06:00
+41
@@ -234,6 +234,9 @@ components:
|
||||
items:
|
||||
type: string
|
||||
example: m1k1o/neko:latest
|
||||
storage_enabled:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
RoomEntry:
|
||||
type: object
|
||||
@@ -330,6 +333,8 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RoomMount'
|
||||
browser_policy:
|
||||
$ref: '#/components/schemas/BrowserPolicy'
|
||||
|
||||
RoomStats:
|
||||
type: object
|
||||
@@ -360,3 +365,39 @@ components:
|
||||
muted:
|
||||
type: boolean
|
||||
example: false
|
||||
|
||||
BrowserPolicy:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum: [ firefox, chromium ]
|
||||
path:
|
||||
type: string
|
||||
example: /usr/lib/firefox/distribution/policies.json
|
||||
content:
|
||||
$ref: '#/components/schemas/BrowserPolicyContent'
|
||||
|
||||
BrowserPolicyContent:
|
||||
type: object
|
||||
properties:
|
||||
extensions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/BrowserPolicyExtension'
|
||||
developer_tools:
|
||||
type: boolean
|
||||
example: true
|
||||
persistent_data:
|
||||
type: boolean
|
||||
example: false
|
||||
|
||||
BrowserPolicyExtension:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: uBlock0@raymondhill.net
|
||||
url:
|
||||
type: string
|
||||
example: https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi
|
||||
|
||||
@@ -1 +1 @@
|
||||
5.2.0-SNAPSHOT
|
||||
5.2.1-SNAPSHOT
|
||||
@@ -21,6 +21,85 @@ import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObj
|
||||
// @ts-ignore
|
||||
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface BrowserPolicy
|
||||
*/
|
||||
export interface BrowserPolicy {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrowserPolicy
|
||||
*/
|
||||
type?: BrowserPolicyTypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrowserPolicy
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
*
|
||||
* @type {BrowserPolicyContent}
|
||||
* @memberof BrowserPolicy
|
||||
*/
|
||||
content?: BrowserPolicyContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum BrowserPolicyTypeEnum {
|
||||
firefox = 'firefox',
|
||||
chromium = 'chromium'
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface BrowserPolicyContent
|
||||
*/
|
||||
export interface BrowserPolicyContent {
|
||||
/**
|
||||
*
|
||||
* @type {Array<BrowserPolicyExtension>}
|
||||
* @memberof BrowserPolicyContent
|
||||
*/
|
||||
extensions?: Array<BrowserPolicyExtension>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof BrowserPolicyContent
|
||||
*/
|
||||
developer_tools?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof BrowserPolicyContent
|
||||
*/
|
||||
persistent_data?: boolean;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface BrowserPolicyExtension
|
||||
*/
|
||||
export interface BrowserPolicyExtension {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrowserPolicyExtension
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BrowserPolicyExtension
|
||||
*/
|
||||
url?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@@ -245,6 +324,12 @@ export interface RoomSettings {
|
||||
* @memberof RoomSettings
|
||||
*/
|
||||
mounts?: Array<RoomMount>;
|
||||
/**
|
||||
*
|
||||
* @type {BrowserPolicy}
|
||||
* @memberof RoomSettings
|
||||
*/
|
||||
browser_policy?: BrowserPolicy;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -289,6 +374,12 @@ export interface RoomsConfig {
|
||||
* @memberof RoomsConfig
|
||||
*/
|
||||
neko_images?: Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof RoomsConfig
|
||||
*/
|
||||
storage_enabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -150,17 +150,45 @@
|
||||
<v-simple-table>
|
||||
<template v-slot:default>
|
||||
<tbody>
|
||||
<tr v-for="({ host_path, container_path }, index) in settings.mounts" :key="index"><td style="width:50%;">{{ host_path }}</td><td>{{ container_path }}</td></tr>
|
||||
<tr v-for="({ type, host_path, container_path }, index) in settings.mounts" :key="index"><td style="width:50%;">{{ host_path }} <v-chip small>{{ type }}</v-chip></td><td>{{ container_path }}</td></tr>
|
||||
</tbody>
|
||||
</template>
|
||||
</v-simple-table>
|
||||
|
||||
<div class="my-3 headline">Browser policy</div>
|
||||
<v-simple-table v-if="settings.browser_policy">
|
||||
<template v-slot:default>
|
||||
<tbody>
|
||||
<tr><th> Type </th><td>{{ settings.browser_policy.type }}</td></tr>
|
||||
<tr><th> Path </th><td>{{ settings.browser_policy.path }}</td></tr>
|
||||
<tr><th> Content </th><td>
|
||||
<v-simple-table>
|
||||
<template v-slot:default>
|
||||
<tbody>
|
||||
<tr><th> Extensions </th><td>{{ BrowserExtensions(settings.browser_policy.content.extensions).join(', ') }}</td></tr>
|
||||
<tr><th> Developer tools </th><td>{{ settings.browser_policy.content.developer_tools }}</td></tr>
|
||||
<tr><th> Persistent data </th><td>{{ settings.browser_policy.content.persistent_data }}</td></tr>
|
||||
</tbody>
|
||||
</template>
|
||||
</v-simple-table>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</template>
|
||||
</v-simple-table>
|
||||
<div v-else> none </div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
|
||||
import { RoomStats, RoomMember, RoomSettings, RoomEntry } from '@/api/index'
|
||||
|
||||
import {
|
||||
RoomStats,
|
||||
RoomMember,
|
||||
RoomSettings,
|
||||
RoomEntry,
|
||||
} from '@/api/index'
|
||||
|
||||
@Component
|
||||
export default class RoomInfo extends Vue {
|
||||
@@ -231,5 +259,27 @@ export default class RoomInfo extends Vue {
|
||||
this.statsLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
get allBrowserExtensions() {
|
||||
if (!this.settings?.browser_policy?.type) return {}
|
||||
|
||||
/*return this.$store.state.browserPolicyExtensions.map(({ text, value }: {
|
||||
text: string;
|
||||
value: Record<BrowserPolicyTypeEnum, BrowserPolicyExtension>;
|
||||
}) => [value[this.settings.browser_policy.type], text])*/
|
||||
|
||||
const obj = {} as Record<string, string>
|
||||
for (const { value, text } of this.$store.state.browserPolicyExtensions) {
|
||||
const id = value[this.settings.browser_policy.type].id
|
||||
obj[id] = text
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
BrowserExtensions(extensions: { id: string }[]) {
|
||||
return extensions.map(({ id }: { id: string }) =>
|
||||
id in this.allBrowserExtensions ? this.allBrowserExtensions[id] : id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -208,10 +208,18 @@
|
||||
<v-btn @click="delEnv(index)" icon color="red"><v-icon>mdi-close</v-icon></v-btn>
|
||||
</div>
|
||||
</v-row>
|
||||
<v-row align="center" no-gutters class="mt-3">
|
||||
<v-row align="center" no-gutters class="my-3">
|
||||
<h2> Mounts </h2>
|
||||
<v-btn @click="data.mounts = [ ...data.mounts, { type: 'private', host_path: '', container_path: '' }]" icon color="green"><v-icon>mdi-plus</v-icon></v-btn>
|
||||
<v-btn :disabled="!storageEnabled" @click="data.mounts = [ ...data.mounts, { type: 'private', host_path: '', container_path: '' }]" icon color="green"><v-icon>mdi-plus</v-icon></v-btn>
|
||||
</v-row>
|
||||
<v-alert
|
||||
border="left"
|
||||
type="warning"
|
||||
v-if="!storageEnabled"
|
||||
>
|
||||
<p><strong>Not available!</strong></p>
|
||||
<p class="mb-0">Mounts are not available, because storage is not enabled.</p>
|
||||
</v-alert>
|
||||
<v-row align="center" class="mb-2" v-for="({ type, host_path, container_path }, index) in data.mounts" :key="index">
|
||||
<v-col class="py-0" cols="2">
|
||||
<v-select
|
||||
@@ -252,6 +260,71 @@
|
||||
</p>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<hr />
|
||||
|
||||
<v-row align="center" no-gutters class="mt-3">
|
||||
<h2 class="my-3">
|
||||
Browser policy
|
||||
</h2>
|
||||
<v-checkbox
|
||||
v-model="browserPolicyEnabled"
|
||||
:disabled="!browserPolicyConfig || !storageEnabled"
|
||||
hide-details
|
||||
class="shrink ml-2 mt-0"
|
||||
></v-checkbox>
|
||||
</v-row>
|
||||
|
||||
<v-alert
|
||||
border="left"
|
||||
type="warning"
|
||||
v-if="!storageEnabled"
|
||||
>
|
||||
<p><strong>Not available!</strong></p>
|
||||
<p class="mb-0">Browser policy is not available, because storage is not enabled.</p>
|
||||
</v-alert>
|
||||
<template v-else-if="browserPolicyConfig">
|
||||
<v-row align="center" no-gutters class="mt-0">
|
||||
<v-col>
|
||||
<v-select
|
||||
v-model="browserPolicyContent.extensions"
|
||||
label="Extensions"
|
||||
:items="browserPolicyExtensions"
|
||||
multiple
|
||||
:disabled="!browserPolicyEnabled"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row align="center">
|
||||
<v-col>
|
||||
<v-checkbox
|
||||
v-model="browserPolicyContent.developer_tools"
|
||||
label="Enable developer tools"
|
||||
hide-details
|
||||
class="shrink ml-2 mt-0"
|
||||
:disabled="!browserPolicyEnabled"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-checkbox
|
||||
v-model="browserPolicyContent.persistent_data"
|
||||
label="Allow persistent data"
|
||||
hide-details
|
||||
class="shrink ml-2 mt-0"
|
||||
:disabled="!browserPolicyEnabled"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<v-alert
|
||||
border="left"
|
||||
type="info"
|
||||
v-else
|
||||
>
|
||||
<p><strong>Not available!</strong></p>
|
||||
<p class="mb-0">Browser policy is not available for this image.</p>
|
||||
</v-alert>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
@@ -276,10 +349,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue, Component, Ref } from 'vue-property-decorator'
|
||||
import { Vue, Component, Ref, Watch } from 'vue-property-decorator'
|
||||
|
||||
import {
|
||||
RoomSettings,
|
||||
BrowserPolicyContent,
|
||||
BrowserPolicyExtension,
|
||||
BrowserPolicyTypeEnum,
|
||||
RoomMountTypeEnum,
|
||||
} from '@/api/index'
|
||||
|
||||
export type VForm = Vue & {
|
||||
@@ -305,9 +382,11 @@ export default class RoomsCreate extends Vue {
|
||||
private videoPipelineEnabled = false
|
||||
private audioPipelineEnabled = false
|
||||
private broadcastPipelineEnabled = false
|
||||
private browserPolicyEnabled = false
|
||||
|
||||
private loading = false
|
||||
private data: RoomSettings = { ...this.$store.state.defaultRoomSettings }
|
||||
private browserPolicyContent: BrowserPolicyContent = { ...this.$store.state.defaultBrowserPolicyContent }
|
||||
private envList: { key: string; val: string }[] = []
|
||||
|
||||
// eslint-disable-next-line
|
||||
@@ -340,6 +419,10 @@ export default class RoomsCreate extends Vue {
|
||||
return this.$store.state.roomsConfig.neko_images
|
||||
}
|
||||
|
||||
get storageEnabled() {
|
||||
return this.$store.state.roomsConfig.storage_enabled
|
||||
}
|
||||
|
||||
get videoCodecs() {
|
||||
return this.$store.state.videoCodecs
|
||||
}
|
||||
@@ -369,6 +452,42 @@ export default class RoomsCreate extends Vue {
|
||||
]
|
||||
}
|
||||
|
||||
get browserPolicyConfig() {
|
||||
const nekoImage = this.data.neko_image
|
||||
if (!nekoImage) return undefined
|
||||
|
||||
return this.$store.state.browserPolicyConfig.find(({ images }: { images: string[] }): boolean => images.includes(nekoImage))
|
||||
}
|
||||
|
||||
get browserPolicyExtensions() {
|
||||
const config = this.browserPolicyConfig
|
||||
if (!config) return []
|
||||
|
||||
return this.$store.state.browserPolicyExtensions.map(({ text, value }: {
|
||||
text: string;
|
||||
value: Record<BrowserPolicyTypeEnum, BrowserPolicyExtension>;
|
||||
}) => {
|
||||
return {
|
||||
text,
|
||||
value: value[config.type as BrowserPolicyTypeEnum],
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Watch('browserPolicyContent.persistent_data')
|
||||
onPersistentDataUpdate(enabled: boolean) {
|
||||
const config = this.browserPolicyConfig
|
||||
if (!config) return
|
||||
|
||||
if (enabled) {
|
||||
// eslint-disable-next-line
|
||||
this.data.mounts = [ ...(this.data.mounts || []), { type: RoomMountTypeEnum.private, host_path: '/profile', container_path: config.profile }]
|
||||
} else {
|
||||
// eslint-disable-next-line
|
||||
this.data.mounts = (this.data.mounts || []).filter(({ type, container_path }) => type != RoomMountTypeEnum.private && container_path != config.profile)
|
||||
}
|
||||
}
|
||||
|
||||
addEnv() {
|
||||
Vue.set(this, 'envList', [ ...this.envList, { key: '', val: '' } ])
|
||||
}
|
||||
@@ -407,6 +526,12 @@ export default class RoomsCreate extends Vue {
|
||||
// eslint-disable-next-line
|
||||
broadcast_pipeline: this.broadcastPipelineEnabled ? this.data.broadcast_pipeline : '',
|
||||
envs,
|
||||
// eslint-disable-next-line
|
||||
browser_policy: this.browserPolicyEnabled && this.browserPolicyConfig ? {
|
||||
type: this.browserPolicyConfig.type,
|
||||
path: this.browserPolicyConfig.path,
|
||||
content: this.browserPolicyContent
|
||||
} : undefined,
|
||||
})
|
||||
this.Clear()
|
||||
this.$emit('finished', true)
|
||||
@@ -436,6 +561,7 @@ export default class RoomsCreate extends Vue {
|
||||
// eslint-disable-next-line
|
||||
neko_image: this.nekoImages[0],
|
||||
}
|
||||
this.browserPolicyContent = { ...this.$store.state.defaultBrowserPolicyContent }
|
||||
this.envList = Object.entries({...this.data.envs}).map(([ key, val ]) => ({ key, val, }))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,30 @@ import {
|
||||
RoomsConfig,
|
||||
RoomEntry,
|
||||
RoomSettings,
|
||||
BrowserPolicyContent,
|
||||
BrowserPolicyTypeEnum,
|
||||
BrowserPolicyExtension,
|
||||
} from '@/api/index'
|
||||
|
||||
export interface BrowserPolicyConfig {
|
||||
type: BrowserPolicyTypeEnum;
|
||||
path: string;
|
||||
profile: string;
|
||||
images: string[];
|
||||
}
|
||||
|
||||
export interface BrowserPolicyExtensions {
|
||||
type: BrowserPolicyTypeEnum;
|
||||
path: string;
|
||||
profile: string;
|
||||
images: string[];
|
||||
}
|
||||
|
||||
export const state = {
|
||||
//
|
||||
// rooms
|
||||
//
|
||||
|
||||
roomsConfig: {} as RoomsConfig,
|
||||
rooms: [] as RoomEntry[],
|
||||
defaultRoomSettings: {
|
||||
@@ -95,6 +116,88 @@ export const state = {
|
||||
"640x400@60",
|
||||
"640x360@60"
|
||||
] as string[],
|
||||
|
||||
//
|
||||
// browser policy
|
||||
//
|
||||
|
||||
browserPolicyConfig: [
|
||||
{
|
||||
type: BrowserPolicyTypeEnum.firefox,
|
||||
path: '/usr/lib/firefox/distribution/policies.json',
|
||||
profile: '/home/neko/.mozilla/firefox/profile.default',
|
||||
images: [ 'm1k1o/neko:latest', 'm1k1o/neko:firefox' ],
|
||||
},
|
||||
{
|
||||
type: BrowserPolicyTypeEnum.firefox,
|
||||
path: '/usr/lib/firefox-esr/distribution/policies.json',
|
||||
profile: '/home/neko/.mozilla/firefox/profile.default',
|
||||
images: [ 'm1k1o/neko:arm-firefox' ],
|
||||
},
|
||||
{
|
||||
type: BrowserPolicyTypeEnum.chromium,
|
||||
path: '/etc/chromium/policies/managed/policies.json',
|
||||
profile: '/home/neko/.config/chromium',
|
||||
images: [ 'm1k1o/neko:chromium', 'm1k1o/neko:arm-chromium', 'm1k1o/neko:ungoogled-chromium' ],
|
||||
},
|
||||
{
|
||||
type: BrowserPolicyTypeEnum.chromium,
|
||||
path: '/etc/opt/chrome/policies/managed/policies.json',
|
||||
profile: '/home/neko/.config/google-chrome',
|
||||
images: [ 'm1k1o/neko:google-chrome' ],
|
||||
},
|
||||
{
|
||||
type: BrowserPolicyTypeEnum.chromium,
|
||||
path: '/etc/brave/policies/managed/policies.json',
|
||||
profile: '/home/neko/.config/brave',
|
||||
images: [ 'm1k1o/neko:brave' ],
|
||||
},
|
||||
] as BrowserPolicyConfig[],
|
||||
browserPolicyExtensions: [
|
||||
{
|
||||
text: 'uBlock Origin',
|
||||
value: {
|
||||
[BrowserPolicyTypeEnum.firefox]: {
|
||||
id: 'uBlock0@raymondhill.net',
|
||||
url: 'https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi',
|
||||
} as BrowserPolicyExtension,
|
||||
[BrowserPolicyTypeEnum.chromium]: {
|
||||
id: 'cjpalhdlnbpafiamejdnhcphjbkeiagm',
|
||||
} as BrowserPolicyExtension,
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'NordVPN',
|
||||
value: {
|
||||
[BrowserPolicyTypeEnum.firefox]: {
|
||||
id: 'nordvpnproxy@nordvpn.com',
|
||||
url: 'https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi',
|
||||
} as BrowserPolicyExtension,
|
||||
[BrowserPolicyTypeEnum.chromium]: {
|
||||
id: 'fjoaledfpmneenckfbpdfhkmimnjocfa',
|
||||
} as BrowserPolicyExtension,
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'SponsorBlock for YouTube',
|
||||
value: {
|
||||
[BrowserPolicyTypeEnum.firefox]: {
|
||||
id: 'sponsorBlocker@ajay.app',
|
||||
url: 'https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi',
|
||||
} as BrowserPolicyExtension,
|
||||
[BrowserPolicyTypeEnum.chromium]: {
|
||||
id: 'mnjggcdmjocbbbhaepdhchncahnbgone',
|
||||
} as BrowserPolicyExtension,
|
||||
},
|
||||
},
|
||||
],
|
||||
defaultBrowserPolicyContent: {
|
||||
extensions: [],
|
||||
// eslint-disable-next-line
|
||||
developer_tools: false,
|
||||
// eslint-disable-next-line
|
||||
persistent_data: false,
|
||||
} as BrowserPolicyContent,
|
||||
}
|
||||
|
||||
export type State = typeof state
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package chromium
|
||||
|
||||
// https://chromeenterprise.google/policies/
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
)
|
||||
|
||||
//go:embed policies.json
|
||||
var policiesJson string
|
||||
|
||||
func Generate(policies types.BrowserPolicyContent) (string, error) {
|
||||
policiesTmpl := map[string]interface{}{}
|
||||
if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//
|
||||
// Extensions
|
||||
//
|
||||
|
||||
ExtensionInstallForcelist := []interface{}{}
|
||||
for _, e := range policies.Extensions {
|
||||
URL := e.URL
|
||||
if URL == "" {
|
||||
URL = "https://clients2.google.com/service/update2/crx"
|
||||
}
|
||||
|
||||
ExtensionInstallForcelist = append(
|
||||
ExtensionInstallForcelist,
|
||||
fmt.Sprintf("%s;%s", e.ID, URL),
|
||||
)
|
||||
}
|
||||
|
||||
ExtensionInstallWhitelist := []interface{}{}
|
||||
for _, e := range policies.Extensions {
|
||||
ExtensionInstallWhitelist = append(
|
||||
ExtensionInstallWhitelist,
|
||||
e.ID,
|
||||
)
|
||||
}
|
||||
|
||||
policiesTmpl["ExtensionInstallForcelist"] = ExtensionInstallForcelist
|
||||
policiesTmpl["ExtensionInstallWhitelist"] = ExtensionInstallWhitelist
|
||||
policiesTmpl["ExtensionInstallBlacklist"] = []interface{}{"*"}
|
||||
|
||||
//
|
||||
// Developer Tools
|
||||
//
|
||||
|
||||
if policies.DeveloperTools {
|
||||
// Allow usage of the Developer Tools
|
||||
policiesTmpl["DeveloperToolsAvailability"] = 1
|
||||
} else {
|
||||
// Disallow usage of the Developer Tools
|
||||
policiesTmpl["DeveloperToolsAvailability"] = 2
|
||||
}
|
||||
|
||||
//
|
||||
// Persistent Data
|
||||
//
|
||||
|
||||
if policies.PersistentData {
|
||||
// Allow all sites to set local data
|
||||
policiesTmpl["DefaultCookiesSetting"] = 1
|
||||
// Restore the last session
|
||||
policiesTmpl["RestoreOnStartup"] = 1
|
||||
} else {
|
||||
// Keep cookies for the duration of the session
|
||||
policiesTmpl["DefaultCookiesSetting"] = 4
|
||||
// Open New Tab Page
|
||||
policiesTmpl["RestoreOnStartup"] = 5
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(policiesTmpl, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package chromium
|
||||
|
||||
// https://chromeenterprise.google/policies/
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Parse(policiesJson string) (*types.BrowserPolicyContent, error) {
|
||||
policies := types.BrowserPolicyContent{}
|
||||
|
||||
policiesTmpl := map[string]interface{}{}
|
||||
if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//
|
||||
// Extensions
|
||||
//
|
||||
|
||||
if extensions, ok := policiesTmpl["ExtensionInstallForcelist"]; ok {
|
||||
policies.Extensions = []types.BrowserPolicyExtension{}
|
||||
for _, val := range extensions.([]interface{}) {
|
||||
s := strings.Split(val.(string), ";")
|
||||
policies.Extensions = append(
|
||||
policies.Extensions,
|
||||
types.BrowserPolicyExtension{
|
||||
ID: s[0],
|
||||
URL: s[1],
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Developer Tools
|
||||
//
|
||||
|
||||
if val, ok := policiesTmpl["DeveloperToolsAvailability"]; ok {
|
||||
policies.DeveloperTools = val.(float64) == 1
|
||||
}
|
||||
|
||||
//
|
||||
// Persistent Data
|
||||
//
|
||||
|
||||
if val, ok := policiesTmpl["DefaultCookiesSetting"]; ok {
|
||||
policies.PersistentData = val.(float64) == 1
|
||||
}
|
||||
|
||||
return &policies, nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"HomepageLocation": "",
|
||||
"AutoFillEnabled": false,
|
||||
"AutofillAddressEnabled": false,
|
||||
"AutofillCreditCardEnabled": false,
|
||||
"BrowserSignin": 0,
|
||||
"DefaultNotificationsSetting": 2,
|
||||
"DeveloperToolsAvailability": 2,
|
||||
"EditBookmarksEnabled": false,
|
||||
"FullscreenAllowed": true,
|
||||
"IncognitoModeAvailability": 1,
|
||||
"SyncDisabled": true,
|
||||
"AutoplayAllowed": true,
|
||||
"BrowserAddPersonEnabled": false,
|
||||
"BrowserGuestModeEnabled": false,
|
||||
"DefaultPopupsSetting": 2,
|
||||
"DownloadRestrictions": 3,
|
||||
"VideoCaptureAllowed": true,
|
||||
"AllowFileSelectionDialogs": false,
|
||||
"PromptForDownloadLocation": false,
|
||||
"BookmarkBarEnabled": false,
|
||||
"PasswordManagerEnabled": false,
|
||||
"URLBlacklist": [
|
||||
"file://*",
|
||||
"chrome://policy"
|
||||
],
|
||||
"ExtensionInstallForcelist": [
|
||||
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
|
||||
"fjoaledfpmneenckfbpdfhkmimnjocfa;https://clients2.google.com/service/update2/crx"
|
||||
],
|
||||
"ExtensionInstallWhitelist": [
|
||||
"cjpalhdlnbpafiamejdnhcphjbkeiagm",
|
||||
"fjoaledfpmneenckfbpdfhkmimnjocfa"
|
||||
],
|
||||
"ExtensionInstallBlacklist": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package policies
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"m1k1o/neko_rooms/internal/policies/chromium"
|
||||
"m1k1o/neko_rooms/internal/policies/firefox"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
)
|
||||
|
||||
func Generate(policies types.BrowserPolicyContent, policyType types.BrowserPolicyType) (string, error) {
|
||||
if policyType == types.ChromiumBrowserPolicy {
|
||||
return chromium.Generate(policies)
|
||||
}
|
||||
|
||||
if policyType == types.FirefoxBrowserPolicy {
|
||||
return firefox.Generate(policies)
|
||||
}
|
||||
|
||||
return "", errors.New("unknown policy type")
|
||||
}
|
||||
|
||||
func Parse(policiesJson string, policyType types.BrowserPolicyType) (*types.BrowserPolicyContent, error) {
|
||||
if policyType == types.ChromiumBrowserPolicy {
|
||||
return chromium.Parse(policiesJson)
|
||||
}
|
||||
|
||||
if policyType == types.FirefoxBrowserPolicy {
|
||||
return firefox.Parse(policiesJson)
|
||||
}
|
||||
|
||||
return nil, errors.New("unknown policy type")
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package firefox
|
||||
|
||||
// https://github.com/mozilla/policy-templates/blob/master/README.md#homepage
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
)
|
||||
|
||||
//go:embed policies.json
|
||||
var policiesJson string
|
||||
|
||||
func Generate(policies types.BrowserPolicyContent) (string, error) {
|
||||
policiesTmpl := struct {
|
||||
Policies map[string]interface{} `json:"policies"`
|
||||
}{}
|
||||
if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//
|
||||
// Extensions
|
||||
//
|
||||
|
||||
ExtensionSettings := map[string]interface{}{}
|
||||
ExtensionSettings["*"] = map[string]interface{}{
|
||||
"installation_mode": "blocked",
|
||||
}
|
||||
|
||||
for _, e := range policies.Extensions {
|
||||
ExtensionSettings[e.ID] = map[string]interface{}{
|
||||
"install_url": e.URL,
|
||||
"installation_mode": "force_installed",
|
||||
}
|
||||
}
|
||||
|
||||
policiesTmpl.Policies["ExtensionSettings"] = ExtensionSettings
|
||||
|
||||
//
|
||||
// Developer Tools
|
||||
//
|
||||
|
||||
policiesTmpl.Policies["DisableDeveloperTools"] = !policies.DeveloperTools
|
||||
|
||||
//
|
||||
// Persistent Data
|
||||
//
|
||||
|
||||
Preferences := policiesTmpl.Policies["Preferences"].(map[string]interface{})
|
||||
Preferences["browser.urlbar.suggest.history"] = policies.PersistentData
|
||||
Preferences["places.history.enabled"] = policies.PersistentData
|
||||
policiesTmpl.Policies["Preferences"] = Preferences
|
||||
policiesTmpl.Policies["SanitizeOnShutdown"] = !policies.PersistentData
|
||||
|
||||
if policies.PersistentData {
|
||||
policiesTmpl.Policies["Homepage"] = map[string]interface{}{
|
||||
"StartPage": "previous-session",
|
||||
}
|
||||
} else {
|
||||
policiesTmpl.Policies["Homepage"] = map[string]interface{}{
|
||||
"StartPage": "homepage",
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(policiesTmpl, "", " ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package firefox
|
||||
|
||||
// https://github.com/mozilla/policy-templates/blob/master/README.md#homepage
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
)
|
||||
|
||||
func Parse(policiesJson string) (*types.BrowserPolicyContent, error) {
|
||||
policies := types.BrowserPolicyContent{}
|
||||
|
||||
policiesTmpl := struct {
|
||||
Policies map[string]interface{} `json:"policies"`
|
||||
}{}
|
||||
if err := json.Unmarshal([]byte(policiesJson), &policiesTmpl); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// empty file
|
||||
if policiesTmpl.Policies == nil {
|
||||
return &policies, nil
|
||||
}
|
||||
|
||||
//
|
||||
// Extensions
|
||||
//
|
||||
|
||||
if extensions, ok := policiesTmpl.Policies["ExtensionSettings"]; ok {
|
||||
policies.Extensions = []types.BrowserPolicyExtension{}
|
||||
for id, val := range extensions.(map[string]interface{}) {
|
||||
if id == "*" {
|
||||
continue
|
||||
}
|
||||
|
||||
data := val.(map[string]interface{})
|
||||
url, _ := data["install_url"].(string)
|
||||
|
||||
policies.Extensions = append(
|
||||
policies.Extensions,
|
||||
types.BrowserPolicyExtension{
|
||||
ID: id,
|
||||
URL: url,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Developer Tools
|
||||
//
|
||||
|
||||
if val, ok := policiesTmpl.Policies["DisableDeveloperTools"]; ok {
|
||||
policies.DeveloperTools = !val.(bool)
|
||||
}
|
||||
|
||||
//
|
||||
// Persistent Data
|
||||
//
|
||||
|
||||
if val, ok := policiesTmpl.Policies["SanitizeOnShutdown"]; ok {
|
||||
policies.PersistentData = !val.(bool)
|
||||
}
|
||||
|
||||
return &policies, nil
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
{
|
||||
"policies": {
|
||||
"BlockAboutAddons": false,
|
||||
"BlockAboutConfig": true,
|
||||
"BlockAboutProfiles": true,
|
||||
"BlockAboutSupport": true,
|
||||
"Bookmarks": [
|
||||
{
|
||||
"Title": "IPLeak",
|
||||
"URL": "https://ipleak.net/",
|
||||
"Favicon": "https://ipleak.net/favicon.ico",
|
||||
"Folder": "Pages",
|
||||
"Placement": "toolbar"
|
||||
},
|
||||
{
|
||||
"Title": "YouTube",
|
||||
"URL": "https://www.youtube.com/",
|
||||
"Favicon": "https://www.youtube.com/favicon.ico",
|
||||
"Folder": "Pages",
|
||||
"Placement": "toolbar"
|
||||
},
|
||||
{
|
||||
"Title": "Google",
|
||||
"URL": "https://www.google.com/",
|
||||
"Favicon": "https://www.google.com/favicon.ico",
|
||||
"Folder": "Pages",
|
||||
"Placement": "toolbar"
|
||||
}
|
||||
],
|
||||
"CaptivePortal": false,
|
||||
"DisableAppUpdate": true,
|
||||
"DisableBuiltinPDFViewer": true,
|
||||
"DisableDeveloperTools": false,
|
||||
"DisableFeedbackCommands": true,
|
||||
"DisableFirefoxAccounts": true,
|
||||
"DisableFirefoxScreenshots": true,
|
||||
"DisableFirefoxStudies": true,
|
||||
"DisableForgetButton": true,
|
||||
"DisableMasterPasswordCreation": true,
|
||||
"DisablePocket": true,
|
||||
"DisablePrivateBrowsing": true,
|
||||
"DisableProfileImport": true,
|
||||
"DisableProfileRefresh": true,
|
||||
"DisableSafeMode": true,
|
||||
"DisableSetDesktopBackground": true,
|
||||
"DisableSystemAddonUpdate": true,
|
||||
"DisableTelemetry": true,
|
||||
"DisplayBookmarksToolbar": false,
|
||||
"DontCheckDefaultBrowser": true,
|
||||
"EnableTrackingProtection": {
|
||||
"Cryptomining": true,
|
||||
"Fingerprinting": true,
|
||||
"Value": true
|
||||
},
|
||||
"ExtensionSettings": {
|
||||
"*": {
|
||||
"installation_mode": "blocked"
|
||||
},
|
||||
"nordvpnproxy@nordvpn.com": {
|
||||
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/nordvpn-proxy-extension/latest.xpi",
|
||||
"installation_mode": "force_installed"
|
||||
},
|
||||
"uBlock0@raymondhill.net": {
|
||||
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi",
|
||||
"installation_mode": "force_installed"
|
||||
}
|
||||
},
|
||||
"ExtensionUpdate": false,
|
||||
"FirefoxHome": {
|
||||
"Highlights": false,
|
||||
"Pocket": false,
|
||||
"Search": true,
|
||||
"Snippets": false,
|
||||
"TopSites": true
|
||||
},
|
||||
"FlashPlugin": {},
|
||||
"HardwareAcceleration": false,
|
||||
"Homepage": {
|
||||
"Additional": [],
|
||||
"StartPage": "home"
|
||||
},
|
||||
"NewTabPage": true,
|
||||
"NoDefaultBookmarks": true,
|
||||
"OfferToSaveLogins": false,
|
||||
"OfferToSaveLoginsDefault": false,
|
||||
"OverrideFirstRunPage": "",
|
||||
"OverridePostUpdatePage": "",
|
||||
"PasswordManagerEnabled": false,
|
||||
"Permissions": {
|
||||
"Camera": {
|
||||
"BlockNewRequests": true
|
||||
},
|
||||
"Location": {
|
||||
"BlockNewRequests": true
|
||||
},
|
||||
"Microphone": {
|
||||
"BlockNewRequests": true
|
||||
},
|
||||
"Notifications": {
|
||||
"BlockNewRequests": true
|
||||
}
|
||||
},
|
||||
"Preferences": {
|
||||
"browser.tabs.warnOnClose": false,
|
||||
"browser.urlbar.suggest.bookmark": false,
|
||||
"browser.urlbar.suggest.history": false,
|
||||
"browser.urlbar.suggest.openpage": false,
|
||||
"datareporting.policy.dataSubmissionPolicyBypassNotification": true,
|
||||
"dom.disable_window_flip": true,
|
||||
"dom.disable_window_move_resize": true,
|
||||
"dom.event.contextmenu.enabled": false,
|
||||
"extensions.getAddons.showPane": false,
|
||||
"places.history.enabled": false,
|
||||
"privacy.file_unique_origin": true,
|
||||
"ui.key.menuAccessKeyFocuses": false
|
||||
},
|
||||
"PromptForDownloadLocation": false,
|
||||
"SanitizeOnShutdown": true
|
||||
}
|
||||
}
|
||||
+37
-1
@@ -3,6 +3,8 @@ package room
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
)
|
||||
|
||||
type RoomLabels struct {
|
||||
@@ -10,6 +12,13 @@ type RoomLabels struct {
|
||||
URL string
|
||||
Epr EprPorts
|
||||
NekoImage string
|
||||
|
||||
BrowserPolicy *BrowserPolicyLabels
|
||||
}
|
||||
|
||||
type BrowserPolicyLabels struct {
|
||||
Type types.BrowserPolicyType
|
||||
Path string
|
||||
}
|
||||
|
||||
func (manager *RoomManagerCtx) extractLabels(labels map[string]string) (*RoomLabels, error) {
|
||||
@@ -48,6 +57,24 @@ func (manager *RoomManagerCtx) extractLabels(labels map[string]string) (*RoomLab
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var browserPolicy *BrowserPolicyLabels
|
||||
if val, ok := labels["m1k1o.neko_rooms.browser_policy"]; ok && val == "true" {
|
||||
policyType, ok := labels["m1k1o.neko_rooms.browser_policy.type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("damaged container labels: browser_policy.type not found")
|
||||
}
|
||||
|
||||
policyPath, ok := labels["m1k1o.neko_rooms.browser_policy.path"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("damaged container labels: browser_policy.path not found")
|
||||
}
|
||||
|
||||
browserPolicy = &BrowserPolicyLabels{
|
||||
Type: types.BrowserPolicyType(policyType),
|
||||
Path: policyPath,
|
||||
}
|
||||
}
|
||||
|
||||
return &RoomLabels{
|
||||
Name: name,
|
||||
URL: url,
|
||||
@@ -56,11 +83,12 @@ func (manager *RoomManagerCtx) extractLabels(labels map[string]string) (*RoomLab
|
||||
Min: uint16(eprMin),
|
||||
Max: uint16(eprMax),
|
||||
},
|
||||
BrowserPolicy: browserPolicy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (manager *RoomManagerCtx) serializeLabels(labels RoomLabels) map[string]string {
|
||||
return map[string]string{
|
||||
labelsMap := map[string]string{
|
||||
"m1k1o.neko_rooms.name": labels.Name,
|
||||
"m1k1o.neko_rooms.url": labels.URL,
|
||||
"m1k1o.neko_rooms.instance": manager.config.InstanceName,
|
||||
@@ -68,4 +96,12 @@ func (manager *RoomManagerCtx) serializeLabels(labels RoomLabels) map[string]str
|
||||
"m1k1o.neko_rooms.epr.max": fmt.Sprintf("%d", labels.Epr.Max),
|
||||
"m1k1o.neko_rooms.neko_image": labels.NekoImage,
|
||||
}
|
||||
|
||||
if labels.BrowserPolicy != nil {
|
||||
labelsMap["m1k1o.neko_rooms.browser_policy"] = "true"
|
||||
labelsMap["m1k1o.neko_rooms.browser_policy.type"] = string(labels.BrowserPolicy.Type)
|
||||
labelsMap["m1k1o.neko_rooms.browser_policy.path"] = labels.BrowserPolicy.Path
|
||||
}
|
||||
|
||||
return labelsMap
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"m1k1o/neko_rooms/internal/config"
|
||||
"m1k1o/neko_rooms/internal/policies"
|
||||
"m1k1o/neko_rooms/internal/types"
|
||||
"m1k1o/neko_rooms/internal/utils"
|
||||
)
|
||||
@@ -60,6 +61,7 @@ func (manager *RoomManagerCtx) Config() types.RoomsConfig {
|
||||
return types.RoomsConfig{
|
||||
Connections: manager.config.EprMax - manager.config.EprMin + 1,
|
||||
NekoImages: manager.config.NekoImages,
|
||||
StorageEnabled: manager.config.StorageEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,11 +217,21 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
|
||||
instanceUrl = instanceUrl + "/"
|
||||
}
|
||||
|
||||
var browserPolicyLabels *BrowserPolicyLabels
|
||||
if settings.BrowserPolicy != nil {
|
||||
browserPolicyLabels = &BrowserPolicyLabels{
|
||||
Type: settings.BrowserPolicy.Type,
|
||||
Path: settings.BrowserPolicy.Path,
|
||||
}
|
||||
}
|
||||
|
||||
labels := manager.serializeLabels(RoomLabels{
|
||||
Name: roomName,
|
||||
URL: instanceUrl + instanceSuffix,
|
||||
Epr: epr,
|
||||
NekoImage: settings.NekoImage,
|
||||
|
||||
BrowserPolicy: browserPolicyLabels,
|
||||
})
|
||||
|
||||
for k, v := range traefikLabels {
|
||||
@@ -241,12 +253,57 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
|
||||
env = append(env, fmt.Sprintf("NEKO_NAT1TO1=%s", strings.Join(manager.config.NAT1To1IPs, ",")))
|
||||
}
|
||||
|
||||
//
|
||||
// Set browser policies
|
||||
//
|
||||
|
||||
if settings.BrowserPolicy != nil {
|
||||
if !manager.config.StorageEnabled {
|
||||
return "", fmt.Errorf("policies cannot be specified, because storage is disabled or unavailable")
|
||||
}
|
||||
|
||||
policyJson, err := policies.Generate(settings.BrowserPolicy.Content, settings.BrowserPolicy.Type)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// create policy path (+ also get host path)
|
||||
policyPath := fmt.Sprintf("/%s-%s-policy.json", roomName, settings.BrowserPolicy.Type)
|
||||
templateInternalPath := path.Join(manager.config.StorageInternal, templateStoragePath)
|
||||
policyInternalPath := path.Join(templateInternalPath, policyPath)
|
||||
|
||||
// create dir if does not exist
|
||||
if _, err := os.Stat(templateInternalPath); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(templateInternalPath, os.ModePerm); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// write policy to file
|
||||
if err := os.WriteFile(policyInternalPath, []byte(policyJson), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// mount policy file
|
||||
settings.Mounts = append(settings.Mounts, types.RoomMount{
|
||||
Type: types.MountTemplate,
|
||||
HostPath: policyPath,
|
||||
ContainerPath: settings.BrowserPolicy.Path,
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// Set container mounts
|
||||
//
|
||||
|
||||
paths := map[string]bool{}
|
||||
mounts := []dockerMount.Mount{}
|
||||
for _, mount := range settings.Mounts {
|
||||
// ignore duplicates
|
||||
if _, ok := paths[mount.ContainerPath]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
readOnly := false
|
||||
|
||||
hostPath := filepath.Clean(mount.HostPath)
|
||||
@@ -309,6 +366,8 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
paths[mount.ContainerPath] = true
|
||||
}
|
||||
|
||||
//
|
||||
@@ -441,11 +500,40 @@ func (manager *RoomManagerCtx) GetSettings(id string) (*types.RoomSettings, erro
|
||||
})
|
||||
}
|
||||
|
||||
var browserPolicy *types.BrowserPolicy
|
||||
if labels.BrowserPolicy != nil {
|
||||
browserPolicy = &types.BrowserPolicy{
|
||||
Type: labels.BrowserPolicy.Type,
|
||||
Path: labels.BrowserPolicy.Path,
|
||||
}
|
||||
|
||||
var policyMount *types.RoomMount
|
||||
for _, mount := range mounts {
|
||||
if mount.ContainerPath == labels.BrowserPolicy.Path {
|
||||
policyMount = &mount
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Refactor.
|
||||
if policyMount != nil && policyMount.Type == types.MountTemplate {
|
||||
templateInternalPath := path.Join(manager.config.StorageInternal, templateStoragePath, policyMount.HostPath)
|
||||
if _, err := os.Stat(templateInternalPath); !os.IsNotExist(err) {
|
||||
if data, err := os.ReadFile(templateInternalPath); err == nil {
|
||||
if content, err := policies.Parse(string(data), labels.BrowserPolicy.Type); err == nil {
|
||||
browserPolicy.Content = *content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings := types.RoomSettings{
|
||||
Name: labels.Name,
|
||||
NekoImage: labels.NekoImage,
|
||||
MaxConnections: labels.Epr.Max - labels.Epr.Min + 1,
|
||||
Mounts: mounts,
|
||||
BrowserPolicy: browserPolicy,
|
||||
}
|
||||
|
||||
err = settings.FromEnv(container.Config.Env)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package types
|
||||
|
||||
type BrowserPolicyType string
|
||||
|
||||
const (
|
||||
ChromiumBrowserPolicy BrowserPolicyType = "chromium"
|
||||
FirefoxBrowserPolicy BrowserPolicyType = "firefox"
|
||||
)
|
||||
|
||||
type BrowserPolicy struct {
|
||||
Type BrowserPolicyType `json:"type"`
|
||||
Path string `json:"path"`
|
||||
Content BrowserPolicyContent `json:"content"`
|
||||
}
|
||||
|
||||
type BrowserPolicyContent struct {
|
||||
Extensions []BrowserPolicyExtension `json:"extensions"`
|
||||
DeveloperTools bool `json:"developer_tools"`
|
||||
PersistentData bool `json:"persistent_data"`
|
||||
}
|
||||
|
||||
type BrowserPolicyExtension struct {
|
||||
ID string `json:"id"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
@@ -26,6 +26,7 @@ var blacklistedEnvs = []string{
|
||||
type RoomsConfig struct {
|
||||
Connections uint16 `json:"connections"`
|
||||
NekoImages []string `json:"neko_images"`
|
||||
StorageEnabled bool `json:"storage_enabled"`
|
||||
}
|
||||
|
||||
type RoomEntry struct {
|
||||
@@ -75,6 +76,8 @@ type RoomSettings struct {
|
||||
|
||||
Envs map[string]string `json:"envs"`
|
||||
Mounts []RoomMount `json:"mounts"`
|
||||
|
||||
BrowserPolicy *BrowserPolicy `json:"browser_policy,omitempty"`
|
||||
}
|
||||
|
||||
func (settings *RoomSettings) ToEnv() []string {
|
||||
|
||||
Reference in New Issue
Block a user