114 | |
115 | {this.props.Online
116 | ?
117 | :
118 | } |
119 | {this.props.TailscaleIPs[0]} |
120 | {hostName} |
121 | {network} |
122 | {
123 | tags
124 | }
125 | |
126 | {this.props.Self
127 | ? "Self"
128 | : this.props.Active
129 | ? this.props.CurAddr != ""
130 | ? "Direct"
131 | : "Relay: " + this.props.Relay
132 | : this.props.Online
133 | ? "Idle"
134 | : "-"
135 | } |
136 | {this.props.ExitNode
137 | ? "Current"
138 | : this.props.ExitNodeOption
139 | ? "Yes"
140 | : "-"
141 | } |
142 | {this.props.OS} |
143 | {this.props.Self
144 | ? "-"
145 | : "" + this.props.TxBytes + " / " + this.props.RxBytes
146 | } |
147 |
);
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # extract name from package.json
2 | PACKAGE_NAME := $(shell awk '/"name":/ {gsub(/[",]/, "", $$2); print $$2}' package.json)
3 | RPM_NAME := cockpit-$(PACKAGE_NAME)
4 | VERSION := $(shell T=$$(git describe 2>/dev/null) || T=1; echo $$T | tr '-' '.')
5 | ifeq ($(TEST_OS),)
6 | TEST_OS = centos-8-stream
7 | endif
8 | export TEST_OS
9 | TARFILE=$(RPM_NAME)-$(VERSION).tar.xz
10 | NODE_CACHE=$(RPM_NAME)-node-$(VERSION).tar.xz
11 | SPEC=$(RPM_NAME).spec
12 | PREFIX ?= /usr/local
13 | APPSTREAMFILE=org.cockpit-project.$(PACKAGE_NAME).metainfo.xml
14 | VM_IMAGE=$(CURDIR)/test/images/$(TEST_OS)
15 | # stamp file to check for node_modules/
16 | NODE_MODULES_TEST=package-lock.json
17 | # one example file in dist/ from bundler to check if that already ran
18 | DIST_TEST=dist/manifest.json
19 | # one example file in pkg/lib to check if it was already checked out
20 | COCKPIT_REPO_STAMP=pkg/lib/cockpit-po-plugin.js
21 | # common arguments for tar, mostly to make the generated tarballs reproducible
22 | TAR_ARGS = --sort=name --mtime "@$(shell git show --no-patch --format='%at')" --mode=go=rX,u+rw,a-s --numeric-owner --owner=0 --group=0
23 |
24 | all: $(DIST_TEST)
25 |
26 | # checkout common files from Cockpit repository required to build this project;
27 | # this has no API stability guarantee, so check out a stable tag when you start
28 | # a new project, use the latest release, and update it from time to time
29 | COCKPIT_REPO_FILES = \
30 | pkg/lib \
31 | test/common \
32 | $(NULL)
33 |
34 | COCKPIT_REPO_URL = https://github.com/cockpit-project/cockpit.git
35 | COCKPIT_REPO_COMMIT = 536834c40ad3e2390a52fb87583f07302e2a29a4 # 294 + 14 commits
36 |
37 | $(COCKPIT_REPO_FILES): $(COCKPIT_REPO_STAMP)
38 | COCKPIT_REPO_TREE = '$(strip $(COCKPIT_REPO_COMMIT))^{tree}'
39 | $(COCKPIT_REPO_STAMP): Makefile
40 | @git rev-list --quiet --objects $(COCKPIT_REPO_TREE) -- 2>/dev/null || \
41 | git fetch --no-tags --no-write-fetch-head --depth=1 $(COCKPIT_REPO_URL) $(COCKPIT_REPO_COMMIT)
42 | git archive $(COCKPIT_REPO_TREE) -- $(COCKPIT_REPO_FILES) | tar x
43 |
44 | #
45 | # i18n
46 | #
47 |
48 | LINGUAS=$(basename $(notdir $(wildcard po/*.po)))
49 |
50 | po/$(PACKAGE_NAME).js.pot:
51 | xgettext --default-domain=$(PACKAGE_NAME) --output=$@ --language=C --keyword= \
52 | --keyword=_:1,1t --keyword=_:1c,2,2t --keyword=C_:1c,2 \
53 | --keyword=N_ --keyword=NC_:1c,2 \
54 | --keyword=gettext:1,1t --keyword=gettext:1c,2,2t \
55 | --keyword=ngettext:1,2,3t --keyword=ngettext:1c,2,3,4t \
56 | --keyword=gettextCatalog.getString:1,3c --keyword=gettextCatalog.getPlural:2,3,4c \
57 | --from-code=UTF-8 $$(find src/ -name '*.js' -o -name '*.jsx')
58 |
59 | po/$(PACKAGE_NAME).html.pot: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
60 | pkg/lib/html2po.js -o $@ $$(find src -name '*.html')
61 |
62 | po/$(PACKAGE_NAME).manifest.pot: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
63 | pkg/lib/manifest2po.js src/manifest.json -o $@
64 |
65 | po/$(PACKAGE_NAME).metainfo.pot: $(APPSTREAMFILE)
66 | xgettext --default-domain=$(PACKAGE_NAME) --output=$@ $<
67 |
68 | po/$(PACKAGE_NAME).pot: po/$(PACKAGE_NAME).html.pot po/$(PACKAGE_NAME).js.pot po/$(PACKAGE_NAME).manifest.pot po/$(PACKAGE_NAME).metainfo.pot
69 | msgcat --sort-output --output-file=$@ $^
70 |
71 | po/LINGUAS:
72 | echo $(LINGUAS) | tr ' ' '\n' > $@
73 |
74 | #
75 | # Build/Install/dist
76 | #
77 |
78 | $(SPEC): packaging/$(SPEC).in $(NODE_MODULES_TEST)
79 | provides=$$(npm ls --omit dev --package-lock-only --depth=Infinity | grep -Eo '[^[:space:]]+@[^[:space:]]+' | sort -u | sed 's/^/Provides: bundled(npm(/; s/\(.*\)@/\1)) = /'); \
80 | awk -v p="$$provides" '{gsub(/%{VERSION}/, "$(VERSION)"); gsub(/%{NPM_PROVIDES}/, p)}1' $< > $@
81 |
82 | $(DIST_TEST): $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP) $(shell find src/ -type f) package.json
83 | NODE_ENV=$(NODE_ENV) npm run build
84 |
85 | watch: $(NODE_MODULES_TEST) $(COCKPIT_REPO_STAMP)
86 | NODE_ENV=$(NODE_ENV) npm run watch
87 |
88 | clean:
89 | rm -rf dist/
90 | rm -f $(SPEC)
91 | rm -f po/LINGUAS
92 |
93 | install: $(DIST_TEST) po/LINGUAS
94 | mkdir -p $(DESTDIR)$(PREFIX)/share/cockpit/$(PACKAGE_NAME)
95 | cp -r dist/* $(DESTDIR)$(PREFIX)/share/cockpit/$(PACKAGE_NAME)
96 | mkdir -p $(DESTDIR)$(PREFIX)/share/metainfo/
97 | msgfmt --xml -d po \
98 | --template $(APPSTREAMFILE) \
99 | -o $(DESTDIR)$(PREFIX)/share/metainfo/$(APPSTREAMFILE)
100 |
101 | # this requires a built source tree and avoids having to install anything system-wide
102 | devel-install: $(DIST_TEST)
103 | mkdir -p ~/.local/share/cockpit
104 | ln -s `pwd`/dist ~/.local/share/cockpit/$(PACKAGE_NAME)
105 |
106 | # assumes that there was symlink set up using the above devel-install target,
107 | # and removes it
108 | devel-uninstall:
109 | rm -f ~/.local/share/cockpit/$(PACKAGE_NAME)
110 |
111 | print-version:
112 | @echo "$(VERSION)"
113 |
114 | dist: $(TARFILE)
115 | @ls -1 $(TARFILE)
116 |
117 | # when building a distribution tarball, call bundler with a 'production' environment
118 | # we don't ship node_modules for license and compactness reasons; we ship a
119 | # pre-built dist/ (so it's not necessary) and ship package-lock.json (so that
120 | # node_modules/ can be reconstructed if necessary)
121 | $(TARFILE): export NODE_ENV=production
122 | $(TARFILE): $(DIST_TEST) $(SPEC)
123 | if type appstream-util >/dev/null 2>&1; then appstream-util validate-relax --nonet *.metainfo.xml; fi
124 | tar --xz $(TAR_ARGS) -cf $(TARFILE) --transform 's,^,$(RPM_NAME)/,' \
125 | --exclude packaging/$(SPEC).in --exclude node_modules \
126 | $$(git ls-files) $(COCKPIT_REPO_FILES) $(NODE_MODULES_TEST) $(SPEC) dist/
127 |
128 | $(NODE_CACHE): $(NODE_MODULES_TEST)
129 | tar --xz $(TAR_ARGS) -cf $@ node_modules
130 |
131 | node-cache: $(NODE_CACHE)
132 |
133 | # convenience target for developers
134 | srpm: $(TARFILE) $(NODE_CACHE) $(SPEC)
135 | rpmbuild -bs \
136 | --define "_sourcedir `pwd`" \
137 | --define "_srcrpmdir `pwd`" \
138 | $(SPEC)
139 |
140 | # convenience target for developers
141 | rpm: $(TARFILE) $(NODE_CACHE) $(SPEC)
142 | mkdir -p "`pwd`/output"
143 | mkdir -p "`pwd`/rpmbuild"
144 | rpmbuild -bb \
145 | --define "_sourcedir `pwd`" \
146 | --define "_specdir `pwd`" \
147 | --define "_builddir `pwd`/rpmbuild" \
148 | --define "_srcrpmdir `pwd`" \
149 | --define "_rpmdir `pwd`/output" \
150 | --define "_buildrootdir `pwd`/build" \
151 | $(SPEC)
152 | find `pwd`/output -name '*.rpm' -printf '%f\n' -exec mv {} . \;
153 | rm -r "`pwd`/rpmbuild"
154 | rm -r "`pwd`/output" "`pwd`/build"
155 |
156 | ifeq ("$(TEST_SCENARIO)","pybridge")
157 | COCKPIT_PYBRIDGE_REF = main
158 | COCKPIT_WHEEL = cockpit-0-py3-none-any.whl
159 |
160 | $(COCKPIT_WHEEL):
161 | pip wheel git+https://github.com/cockpit-project/cockpit.git@${COCKPIT_PYBRIDGE_REF}
162 |
163 | VM_DEPENDS = $(COCKPIT_WHEEL)
164 | VM_CUSTOMIZE_FLAGS = --install $(COCKPIT_WHEEL)
165 | endif
166 |
167 | # build a VM with locally built distro pkgs installed
168 | # disable networking, VM images have mock/pbuilder with the common build dependencies pre-installed
169 | $(VM_IMAGE): $(TARFILE) $(NODE_CACHE) bots test/vm.install $(VM_DEPENDS)
170 | bots/image-customize --no-network --fresh \
171 | $(VM_CUSTOMIZE_FLAGS) \
172 | --upload $(NODE_CACHE):/var/tmp/ --build $(TARFILE) \
173 | --script $(CURDIR)/test/vm.install $(TEST_OS)
174 |
175 | # convenience target for the above
176 | vm: $(VM_IMAGE)
177 | @echo $(VM_IMAGE)
178 |
179 | # convenience target to print the filename of the test image
180 | print-vm:
181 | @echo $(VM_IMAGE)
182 |
183 | # convenience target to setup all the bits needed for the integration tests
184 | # without actually running them
185 | prepare-check: $(NODE_MODULES_TEST) $(VM_IMAGE) test/common
186 |
187 | # run the browser integration tests; skip check for SELinux denials
188 | # this will run all tests/check-* and format them as TAP
189 | check: prepare-check
190 | TEST_AUDIT_NO_SELINUX=1 test/common/run-tests ${RUN_TESTS_OPTIONS}
191 |
192 | # checkout Cockpit's bots for standard test VM images and API to launch them
193 | bots: $(COCKPIT_REPO_STAMP)
194 | test/common/make-bots
195 |
196 | $(NODE_MODULES_TEST): package.json
197 | # if it exists already, npm install won't update it; force that so that we always get up-to-date packages
198 | rm -f package-lock.json
199 | # unset NODE_ENV, skips devDependencies otherwise
200 | env -u NODE_ENV npm install --ignore-scripts
201 | env -u NODE_ENV npm prune
202 |
203 | .PHONY: all clean install devel-install devel-uninstall print-version dist node-cache rpm prepare-check check vm print-vm
204 |
--------------------------------------------------------------------------------
/@types/cockpitjs/index.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Cockpit {
2 | /**********************************
3 | * Some helpful primitive typedefs
4 | *********************************/
5 |
6 | type integer = number; //A typedef for an integer. Doesn't actually prevent compilation, but provides an IDE hint
7 |
8 | /**********************************
9 | * Cockpit D-Bus
10 | * http://cockpit-project.org/guide/latest/cockpit-dbus.html
11 | *********************************/
12 |
13 | type BYTE = number;
14 | type BOOLEAN = boolean;
15 | type INT16 = number;
16 | type UINT16 = number;
17 | type INT32 = number;
18 | type UINT32 = number;
19 | type INT64 = number;
20 | type UINT64 = number;
21 | type DOUBLE = number;
22 | type STRING = string;
23 | type OBJECT_PATH = string;
24 | type SIGNATURE = string;
25 | type ARRAY_BYTE = string[];
26 | type ARRAY_DICT_ENTRY_STRING = object;
27 | type ARRAY_DICT_ENTRY_OTHER = object;
28 | type ARRAY_OTHER = any[];
29 | interface VARIANT {
30 | "t": STRING,
31 | "v": any
32 | }
33 | //TODO - Not sure on specifics for handle
34 | type HANDLE = object;
35 |
36 | interface DBusOptions {
37 | "bus" : string
38 | "host" : string
39 | "superuser" : string
40 | "track" : string
41 | }
42 |
43 | interface DBusProxy {
44 | client : string
45 | path : string
46 | iface : string
47 | valid : boolean
48 | data : object
49 |
50 | }
51 |
52 | //Todo unfinished
53 | interface DBusClient {
54 |
55 | }
56 |
57 | /**********************************
58 | * Cockpit File Access
59 | * http://cockpit-project.org/guide/latest/cockpit-file.html
60 | **********************************/
61 |
62 | interface ParsingFunction {
63 | (data: string) : string
64 | }
65 |
66 | interface StringifyingFunction {
67 | (data: string) : string
68 | }
69 |
70 | interface SyntaxObject {
71 | parse: ParsingFunction
72 | stringify: StringifyingFunction
73 | }
74 |
75 | interface FileAccessOptions {
76 | syntax?: SyntaxObject,
77 | binary?: boolean,
78 | max_read_size?: integer,
79 | superuser?: string,
80 | host?: string
81 | }
82 |
83 | interface FileReadDoneCallback {
84 | (content: string, tag: string) : void
85 | }
86 |
87 | interface FileReadFailCallback {
88 | (error: string) : void
89 | }
90 |
91 | interface FileReadPromise {
92 | done (callback : FileReadDoneCallback) : FileReadPromise
93 | fail (callback : FileReadFailCallback) : FileReadPromise
94 | }
95 |
96 | interface FileReplaceDoneCallback {
97 | (newTag: string) : void
98 | }
99 |
100 | interface FileReplaceFailCallback {
101 | (error: string) : void
102 | }
103 |
104 | interface FileReplacePromise {
105 | done (callback : FileReplaceDoneCallback) : FileReplacePromise
106 | fail (callback : FileReplaceFailCallback) : FileReplacePromise
107 | }
108 |
109 | interface FileModifyDoneCallback {
110 | (newContent : string, newTag: string) : void
111 | }
112 |
113 | interface FileModifyFailCallback {
114 | (error: string) : void
115 | }
116 |
117 | interface FileModifyPromise {
118 | done (callback : FileModifyDoneCallback) : FileModifyPromise
119 | fail (callback : FileModifyFailCallback) : FileModifyPromise
120 | }
121 |
122 | interface FileWatchCallback {
123 | content : string,
124 | tag : string,
125 | error? : any //TODO - what is the error content?
126 | }
127 |
128 | interface File {
129 | read () : FileReadPromise
130 | replace (content : string, expected_tag?: string) : FileReplacePromise
131 | modify (callback : any, initial_content?: string, initial_tag?: string) : FileModifyPromise
132 | watch (callback : FileWatchCallback) : void
133 | close () : void
134 | }
135 |
136 | /**********************************
137 | * Cockpit Processes
138 | * http://cockpit-project.org/guide/latest/cockpit-spawn.html
139 | **********************************/
140 |
141 | interface ProcessFailureException {
142 | message?: string
143 | problem?: string
144 | exit_status?: integer
145 | exit_signal?: string
146 | }
147 |
148 | enum ProcessProblemCodes {
149 | "access-denied", //"The user is not permitted to perform the action in question."
150 | "authentication-failed", //"User authentication failed."
151 | "internal-error", //"An unexpected internal error without further info. This should not happen during the normal course of operations."
152 | "no-cockpit", //"The system does not have a compatible version of Cockpit installed or installed properly."
153 | "no-session", //"Cockpit is not logged in."
154 | "not-found", //"Something specifically requested was not found, such as a file, executable etc."
155 | "terminated", //"Something was terminated forcibly, such as a connection, process session, etc."
156 | "timeout", //"Something timed out."
157 | "unknown-hostkey", //"The remote host had an unexpected or unknown key."
158 | "no-forwarding" //"Could not forward authentication credentials to the remote host."
159 | }
160 |
161 | interface ProcessPromiseDoneCallback {
162 | (data: string, message?: string) : void
163 | }
164 |
165 | interface ProcessPromiseFailCallback {
166 | (exception: ProcessFailureException, data?: string) : void
167 | }
168 |
169 | interface ProcessPromiseStreamCallback {
170 | (data: string) : void
171 | }
172 |
173 | interface ProcessPromise {
174 | done( callback: ProcessPromiseDoneCallback ) : ProcessPromise,
175 | fail( callback: ProcessPromiseFailCallback ) : ProcessPromise,
176 | stream( callback: ProcessPromiseStreamCallback ) : ProcessPromise,
177 | input( data: string, stream?: boolean ) : ProcessPromise,
178 | close( problem?: ProcessProblemCodes ) : ProcessPromise,
179 | }
180 |
181 | /**********************************
182 | * Cockpit User Session
183 | * http://cockpit-project.org/guide/latest/cockpit-login.html
184 | **********************************/
185 |
186 | interface UserSessionPermission {
187 | allowed : boolean
188 | onChanged : any //TODO need to see how to do events in TS
189 | close() : void
190 | }
191 |
192 | interface UserSessionObject {
193 | onchanged : any
194 | }
195 |
196 | interface UserSessionDetails {
197 | "id" : string //This is unix user id.
198 | "name" : string //This is the unix user name like "root".
199 | "full_name" : string //This is a readable name for the user.
200 | "groups" : string //This is an array of group names to which the user belongs.
201 | "home" : string //This is user's home directory.
202 | "shell" : string //This is unix user shell.
203 | }
204 |
205 | interface UserSessionPromiseDoneCallback {
206 | (user: UserSessionDetails) : void
207 | }
208 |
209 | interface UserSessionPromiseFailCallback { //Todo - is this defined?
210 |
211 | }
212 |
213 | interface UserSessionPromise {
214 |
215 | }
216 |
217 | /**********************************
218 | * Cockpit Object
219 | * Generally brought into your app in the root HTML file via a