| @@ -0,0 +1,27 | |||||
|
|
1 | { | |||
|
|
2 | "env": { | |||
|
|
3 | "browser": true, | |||
|
|
4 | "commonjs": true, | |||
|
|
5 | "amd": true, | |||
|
|
6 | "node": true | |||
|
|
7 | }, | |||
|
|
8 | "parserOptions": { | |||
|
|
9 | "ecmaFeatures": { | |||
|
|
10 | "jsx": true | |||
|
|
11 | }, | |||
|
|
12 | "sourceType": "module" | |||
|
|
13 | }, | |||
|
|
14 | "extends": "eslint:recommended", | |||
|
|
15 | "rules": { | |||
|
|
16 | "no-const-assign": "warn", | |||
|
|
17 | "no-this-before-super": "warn", | |||
|
|
18 | "no-undef": "error", | |||
|
|
19 | "no-unreachable": "warn", | |||
|
|
20 | "no-unused-vars": "warn", | |||
|
|
21 | "constructor-super": "warn", | |||
|
|
22 | "valid-typeof": "warn", | |||
|
|
23 | "semi" : "warn", | |||
|
|
24 | "no-invalid-this" : "error", | |||
|
|
25 | "no-console": "off" | |||
|
|
26 | } | |||
|
|
27 | } No newline at end of file | |||
| @@ -0,0 +1,16 | |||||
|
|
1 | { | |||
|
|
2 | "java.configuration.updateBuildConfiguration": "disabled", | |||
|
|
3 | "tslint.enable": true, | |||
|
|
4 | "search.exclude": { | |||
|
|
5 | "**/node_modules": true, | |||
|
|
6 | "**/bower_components": true, | |||
|
|
7 | "/build": true | |||
|
|
8 | }, | |||
|
|
9 | "files.watcherExclude": { | |||
|
|
10 | "**/.git/objects/**": true, | |||
|
|
11 | "**/.git/subtree-cache/**": true, | |||
|
|
12 | "**/node_modules/**": true, | |||
|
|
13 | "/build": true | |||
|
|
14 | }, | |||
|
|
15 | "editor.minimap.enabled": false | |||
|
|
16 | } No newline at end of file | |||
| @@ -0,0 +1,276 | |||||
|
|
1 | // если версия явно не заданы вычисляем ее из тэга ревизии v.{num}*** | |||
|
|
2 | // результатом будет версия '{num}.{distance}' где distance - расстояние от | |||
|
|
3 | // текущей ревизии до ревизии с тэгом | |||
|
|
4 | def tagDistance = 0; | |||
|
|
5 | def isRelease = false; | |||
|
|
6 | ||||
|
|
7 | if (!version) { | |||
|
|
8 | ||||
|
|
9 | def rev = ["hg", "log", "-r", ".", "--template", "{latesttag('re:^v') % '{tag}-{distance}'}"].execute().text.trim(); | |||
|
|
10 | ||||
|
|
11 | def tagVersion; | |||
|
|
12 | ||||
|
|
13 | def match = (rev =~ /^v(\d+\.\d+\.\d+).*-(\d+)$/); | |||
|
|
14 | ||||
|
|
15 | if (match.size()) { | |||
|
|
16 | tagVersion = match[0][1]; | |||
|
|
17 | tagDistance = match[0][2].toInteger(); | |||
|
|
18 | ||||
|
|
19 | version = tagVersion; | |||
|
|
20 | ||||
|
|
21 | if (tagDistance > 0) | |||
|
|
22 | version++; | |||
|
|
23 | } else { | |||
|
|
24 | throw new Exception("A version must be specied"); | |||
|
|
25 | } | |||
|
|
26 | } else { | |||
|
|
27 | println "explicit version: $version"; | |||
|
|
28 | } | |||
|
|
29 | ||||
|
|
30 | if (hasProperty('versionSuffix') && versionSuffix) { | |||
|
|
31 | version += "-$versionSuffix" | |||
|
|
32 | } | |||
|
|
33 | ||||
|
|
34 | if(!npmName) | |||
|
|
35 | npmName = name; | |||
|
|
36 | ||||
|
|
37 | if (hasProperty('release')) { | |||
|
|
38 | isRelease = (release != 'false') | |||
|
|
39 | } else { | |||
|
|
40 | isRelease = (tagDistance == 0); | |||
|
|
41 | } | |||
|
|
42 | ||||
|
|
43 | if(!["amd", "commonjs", "system", "umd", "es6", "esnext"].contains(jsmodule)) | |||
|
|
44 | throw new Exception("Invalid jsmodule specified: $jsmodule"); | |||
|
|
45 | if(!["es3", "es5", "es6", "es2016", "es2017", "esnext"].contains(target)) | |||
|
|
46 | throw new Exception("Invalid target specified: $target") | |||
|
|
47 | ||||
|
|
48 | def targetLibs = [ | |||
|
|
49 | "es3" : "es5,es2015.promise,es2015.symbol,dom,scripthost", | |||
|
|
50 | "es5" : "es5,es2015.promise,es2015.symbol,dom,scripthost" | |||
|
|
51 | ]; | |||
|
|
52 | ||||
|
|
53 | ext.packageName="@$npmScope/$npmName"; | |||
|
|
54 | ||||
|
|
55 | def srcDir = "$projectDir/src" | |||
|
|
56 | def typingsDir = "$srcDir/typings" | |||
|
|
57 | def distDir = "$buildDir/dist" | |||
|
|
58 | def testDir = "$buildDir/test" | |||
|
|
59 | def lib = targetLibs[target] ?: "${target},dom"; | |||
|
|
60 | ||||
|
|
61 | println "lib: $lib"; | |||
|
|
62 | ||||
|
|
63 | def sourceSets = ["main", "amd", "cjs"]; | |||
|
|
64 | def testSets = ["test", "testAmd", "testCjs"]; | |||
|
|
65 | ||||
|
|
66 | task beforeBuild { | |||
|
|
67 | } | |||
|
|
68 | ||||
|
|
69 | def createSoursetTasks = { String name, String outDir -> | |||
|
|
70 | def setName = name.capitalize(); | |||
|
|
71 | ||||
|
|
72 | def compileDir = "$buildDir/compile/$name" | |||
|
|
73 | def declDir = "$typingsDir/$name" | |||
|
|
74 | def setDir = "$projectDir/src/$name" | |||
|
|
75 | def jsDir = outDir; | |||
|
|
76 | ||||
|
|
77 | def beforeBuildTask = task "beforeBuild$setName"(dependsOn: beforeBuild) { | |||
|
|
78 | } | |||
|
|
79 | ||||
|
|
80 | def copyJsTask = task "copyJs$setName"(dependsOn: beforeBuildTask, type: Copy) { | |||
|
|
81 | from "$setDir/js" | |||
|
|
82 | into jsDir | |||
|
|
83 | } | |||
|
|
84 | ||||
|
|
85 | def lintJsTask = task "lintJs$setName"(dependsOn: beforeBuildTask, type: Exec) { | |||
|
|
86 | inputs.dir("$setDir/js/").skipWhenEmpty(); | |||
|
|
87 | commandLine "eslint", '--format', 'stylish', "$setDir/js/" | |||
|
|
88 | } | |||
|
|
89 | ||||
|
|
90 | def compileTsTask = task "compileTs$setName"(dependsOn: beforeBuildTask, type: Exec) { | |||
|
|
91 | inputs.dir("$setDir/ts").skipWhenEmpty() | |||
|
|
92 | inputs.file("$srcDir/tsconfig.json") | |||
|
|
93 | inputs.file("$setDir/tsconfig.json") | |||
|
|
94 | outputs.dir(compileDir) | |||
|
|
95 | outputs.dir(declDir) | |||
|
|
96 | ||||
|
|
97 | commandLine 'node_modules/.bin/tsc', | |||
|
|
98 | '-p', "$setDir/tsconfig.json", | |||
|
|
99 | '-t', target, | |||
|
|
100 | '-m', jsmodule, | |||
|
|
101 | '-d', | |||
|
|
102 | '--outDir', compileDir, | |||
|
|
103 | '--declarationDir', declDir | |||
|
|
104 | ||||
|
|
105 | if (lib) | |||
|
|
106 | args '--lib', lib | |||
|
|
107 | } | |||
|
|
108 | ||||
|
|
109 | def copyTsOutputTask = task "copyTsOutput$setName"(dependsOn: compileTsTask, type: Copy) { | |||
|
|
110 | from compileDir | |||
|
|
111 | into jsDir | |||
|
|
112 | } | |||
|
|
113 | ||||
|
|
114 | def copyTypingsTask = task "copyTypings$setName"(dependsOn: compileTsTask, type: Copy) { | |||
|
|
115 | from declDir | |||
|
|
116 | into jsDir | |||
|
|
117 | } | |||
|
|
118 | ||||
|
|
119 | def copyResourcesTask = task "copyResources$setName"(dependsOn: beforeBuildTask, type: Copy) { | |||
|
|
120 | from "$setDir/resources" | |||
|
|
121 | into outDir | |||
|
|
122 | } | |||
|
|
123 | ||||
|
|
124 | task "build$setName" { | |||
|
|
125 | dependsOn copyTypingsTask, | |||
|
|
126 | copyTsOutputTask, | |||
|
|
127 | copyJsTask, | |||
|
|
128 | copyResourcesTask, | |||
|
|
129 | lintJsTask | |||
|
|
130 | } | |||
|
|
131 | } | |||
|
|
132 | ||||
|
|
133 | task printVersion { | |||
|
|
134 | doLast { | |||
|
|
135 | println "version: $version"; | |||
|
|
136 | println "isRelease: $isRelease, tagDistance: $tagDistance"; | |||
|
|
137 | println "packageName: $packageName"; | |||
|
|
138 | println "bundle: ${pack.outputs.files.join(',')}"; | |||
|
|
139 | println "target: $target"; | |||
|
|
140 | println "module: $jsmodule"; | |||
|
|
141 | } | |||
|
|
142 | } | |||
|
|
143 | ||||
|
|
144 | task clean { | |||
|
|
145 | doLast { | |||
|
|
146 | delete buildDir | |||
|
|
147 | delete typingsDir | |||
|
|
148 | } | |||
|
|
149 | } | |||
|
|
150 | ||||
|
|
151 | task _initBuild { | |||
|
|
152 | mustRunAfter clean | |||
|
|
153 | ||||
|
|
154 | def buildInfoFile = "$buildDir/platform"; | |||
|
|
155 | inputs.property('target',target); | |||
|
|
156 | inputs.property('jsmodule',jsmodule); | |||
|
|
157 | outputs.file(buildInfoFile); | |||
|
|
158 | ||||
|
|
159 | doLast { | |||
|
|
160 | delete buildDir | |||
|
|
161 | mkdir buildDir | |||
|
|
162 | ||||
|
|
163 | def f = new File(buildInfoFile); | |||
|
|
164 | f << "$target-$jsmodule"; | |||
|
|
165 | } | |||
|
|
166 | } | |||
|
|
167 | ||||
|
|
168 | task cleanNpm { | |||
|
|
169 | doLast { | |||
|
|
170 | delete 'node_modules' | |||
|
|
171 | } | |||
|
|
172 | } | |||
|
|
173 | ||||
|
|
174 | task _npmInstall() { | |||
|
|
175 | inputs.file("package.json") | |||
|
|
176 | outputs.dir("node_modules") | |||
|
|
177 | doLast { | |||
|
|
178 | exec { | |||
|
|
179 | commandLine 'npm', 'install' | |||
|
|
180 | } | |||
|
|
181 | } | |||
|
|
182 | } | |||
|
|
183 | ||||
|
|
184 | beforeBuild { | |||
|
|
185 | dependsOn _initBuild | |||
|
|
186 | dependsOn _npmInstall | |||
|
|
187 | } | |||
|
|
188 | ||||
|
|
189 | sourceSets.each { createSoursetTasks(it, distDir) } | |||
|
|
190 | ||||
|
|
191 | testSets.each { createSoursetTasks(it, testDir) } | |||
|
|
192 | ||||
|
|
193 | compileTsAmd { | |||
|
|
194 | dependsOn compileTsMain | |||
|
|
195 | } | |||
|
|
196 | ||||
|
|
197 | compileTsCjs { | |||
|
|
198 | dependsOn compileTsMain | |||
|
|
199 | } | |||
|
|
200 | ||||
|
|
201 | task build(dependsOn: buildMain) { | |||
|
|
202 | if (jsmodule == "amd") | |||
|
|
203 | dependsOn buildAmd | |||
|
|
204 | if (jsmodule == "commonjs") | |||
|
|
205 | dependsOn buildCjs | |||
|
|
206 | } | |||
|
|
207 | ||||
|
|
208 | compileTsTest { | |||
|
|
209 | dependsOn build | |||
|
|
210 | } | |||
|
|
211 | ||||
|
|
212 | compileTsTestAmd { | |||
|
|
213 | dependsOn compileTsTest | |||
|
|
214 | } | |||
|
|
215 | ||||
|
|
216 | compileTsTestCjs { | |||
|
|
217 | dependsOn compileTsTest | |||
|
|
218 | } | |||
|
|
219 | ||||
|
|
220 | task _installLocalCjsDependency(dependsOn: [buildTestCjs, "_packageMeta"], type: Exec) { | |||
|
|
221 | inputs.file("$distDir/package.json") | |||
|
|
222 | outputs.upToDateWhen { | |||
|
|
223 | new File("$testDir/$packageName").exists() | |||
|
|
224 | } | |||
|
|
225 | ||||
|
|
226 | workingDir testDir | |||
|
|
227 | ||||
|
|
228 | commandLine 'npm', 'install', '--no-save', '--force', distDir | |||
|
|
229 | } | |||
|
|
230 | ||||
|
|
231 | task test(dependsOn: [buildTest], type: Exec) { | |||
|
|
232 | if (jsmodule == "amd") | |||
|
|
233 | dependsOn buildTestAmd | |||
|
|
234 | if (jsmodule == "commonjs") { | |||
|
|
235 | dependsOn buildTestCjs | |||
|
|
236 | dependsOn _installLocalCjsDependency | |||
|
|
237 | } | |||
|
|
238 | ||||
|
|
239 | commandLine 'node', "$testDir/run-tests.js" | |||
|
|
240 | } | |||
|
|
241 | ||||
|
|
242 | task _packageMeta(type: Copy) { | |||
|
|
243 | mustRunAfter build | |||
|
|
244 | ||||
|
|
245 | inputs.property("version", version) | |||
|
|
246 | from('.') { | |||
|
|
247 | include '.npmignore', 'readme.md', 'license', 'history.md' | |||
|
|
248 | } | |||
|
|
249 | from("package.${jsmodule}.json") { | |||
|
|
250 | expand project.properties | |||
|
|
251 | rename { "package.json" } | |||
|
|
252 | } | |||
|
|
253 | into distDir | |||
|
|
254 | } | |||
|
|
255 | ||||
|
|
256 | task pack(dependsOn: [build, _packageMeta], type: Exec) { | |||
|
|
257 | workingDir distDir | |||
|
|
258 | outputs.file("$npmScope-$npmName-${version}.tgz") | |||
|
|
259 | ||||
|
|
260 | commandLine 'npm', 'pack' | |||
|
|
261 | } | |||
|
|
262 | ||||
|
|
263 | task publish(dependsOn: [build, _packageMeta], type: Exec) { | |||
|
|
264 | doFirst { | |||
|
|
265 | if (!isRelease) | |||
|
|
266 | throw new Exception("Can't publish an unreleased version"); | |||
|
|
267 | } | |||
|
|
268 | workingDir distDir | |||
|
|
269 | ||||
|
|
270 | commandLine 'npm', 'publish', '--access', 'public' | |||
|
|
271 | } | |||
|
|
272 | ||||
|
|
273 | task markRelease(type: Exec) { | |||
|
|
274 | onlyIf { tagDistance > 1 } | |||
|
|
275 | commandLine "hg", "tag", "v$version"; | |||
|
|
276 | } No newline at end of file | |||
| @@ -0,0 +1,9 | |||||
|
|
1 | version= | |||
|
|
2 | author=Implab team | |||
|
|
3 | jsmodule=amd | |||
|
|
4 | target=es5 | |||
|
|
5 | description=The simple framework for writing a RESTful application | |||
|
|
6 | license=BSD-2-Clause | |||
|
|
7 | repository=https://bitbucket.org/implab/implabjs-web | |||
|
|
8 | npmScope=implab | |||
|
|
9 | npmName=web No newline at end of file | |||
| 1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
| @@ -0,0 +1,5 | |||||
|
|
1 | distributionBase=GRADLE_USER_HOME | |||
|
|
2 | distributionPath=wrapper/dists | |||
|
|
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip | |||
|
|
4 | zipStoreBase=GRADLE_USER_HOME | |||
|
|
5 | zipStorePath=wrapper/dists | |||
| @@ -0,0 +1,172 | |||||
|
|
1 | #!/usr/bin/env sh | |||
|
|
2 | ||||
|
|
3 | ############################################################################## | |||
|
|
4 | ## | |||
|
|
5 | ## Gradle start up script for UN*X | |||
|
|
6 | ## | |||
|
|
7 | ############################################################################## | |||
|
|
8 | ||||
|
|
9 | # Attempt to set APP_HOME | |||
|
|
10 | # Resolve links: $0 may be a link | |||
|
|
11 | PRG="$0" | |||
|
|
12 | # Need this for relative symlinks. | |||
|
|
13 | while [ -h "$PRG" ] ; do | |||
|
|
14 | ls=`ls -ld "$PRG"` | |||
|
|
15 | link=`expr "$ls" : '.*-> \(.*\)$'` | |||
|
|
16 | if expr "$link" : '/.*' > /dev/null; then | |||
|
|
17 | PRG="$link" | |||
|
|
18 | else | |||
|
|
19 | PRG=`dirname "$PRG"`"/$link" | |||
|
|
20 | fi | |||
|
|
21 | done | |||
|
|
22 | SAVED="`pwd`" | |||
|
|
23 | cd "`dirname \"$PRG\"`/" >/dev/null | |||
|
|
24 | APP_HOME="`pwd -P`" | |||
|
|
25 | cd "$SAVED" >/dev/null | |||
|
|
26 | ||||
|
|
27 | APP_NAME="Gradle" | |||
|
|
28 | APP_BASE_NAME=`basename "$0"` | |||
|
|
29 | ||||
|
|
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
|
|
31 | DEFAULT_JVM_OPTS='"-Xmx64m"' | |||
|
|
32 | ||||
|
|
33 | # Use the maximum available, or set MAX_FD != -1 to use that value. | |||
|
|
34 | MAX_FD="maximum" | |||
|
|
35 | ||||
|
|
36 | warn () { | |||
|
|
37 | echo "$*" | |||
|
|
38 | } | |||
|
|
39 | ||||
|
|
40 | die () { | |||
|
|
41 | echo | |||
|
|
42 | echo "$*" | |||
|
|
43 | echo | |||
|
|
44 | exit 1 | |||
|
|
45 | } | |||
|
|
46 | ||||
|
|
47 | # OS specific support (must be 'true' or 'false'). | |||
|
|
48 | cygwin=false | |||
|
|
49 | msys=false | |||
|
|
50 | darwin=false | |||
|
|
51 | nonstop=false | |||
|
|
52 | case "`uname`" in | |||
|
|
53 | CYGWIN* ) | |||
|
|
54 | cygwin=true | |||
|
|
55 | ;; | |||
|
|
56 | Darwin* ) | |||
|
|
57 | darwin=true | |||
|
|
58 | ;; | |||
|
|
59 | MINGW* ) | |||
|
|
60 | msys=true | |||
|
|
61 | ;; | |||
|
|
62 | NONSTOP* ) | |||
|
|
63 | nonstop=true | |||
|
|
64 | ;; | |||
|
|
65 | esac | |||
|
|
66 | ||||
|
|
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |||
|
|
68 | ||||
|
|
69 | # Determine the Java command to use to start the JVM. | |||
|
|
70 | if [ -n "$JAVA_HOME" ] ; then | |||
|
|
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |||
|
|
72 | # IBM's JDK on AIX uses strange locations for the executables | |||
|
|
73 | JAVACMD="$JAVA_HOME/jre/sh/java" | |||
|
|
74 | else | |||
|
|
75 | JAVACMD="$JAVA_HOME/bin/java" | |||
|
|
76 | fi | |||
|
|
77 | if [ ! -x "$JAVACMD" ] ; then | |||
|
|
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |||
|
|
79 | ||||
|
|
80 | Please set the JAVA_HOME variable in your environment to match the | |||
|
|
81 | location of your Java installation." | |||
|
|
82 | fi | |||
|
|
83 | else | |||
|
|
84 | JAVACMD="java" | |||
|
|
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
|
|
86 | ||||
|
|
87 | Please set the JAVA_HOME variable in your environment to match the | |||
|
|
88 | location of your Java installation." | |||
|
|
89 | fi | |||
|
|
90 | ||||
|
|
91 | # Increase the maximum file descriptors if we can. | |||
|
|
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then | |||
|
|
93 | MAX_FD_LIMIT=`ulimit -H -n` | |||
|
|
94 | if [ $? -eq 0 ] ; then | |||
|
|
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |||
|
|
96 | MAX_FD="$MAX_FD_LIMIT" | |||
|
|
97 | fi | |||
|
|
98 | ulimit -n $MAX_FD | |||
|
|
99 | if [ $? -ne 0 ] ; then | |||
|
|
100 | warn "Could not set maximum file descriptor limit: $MAX_FD" | |||
|
|
101 | fi | |||
|
|
102 | else | |||
|
|
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |||
|
|
104 | fi | |||
|
|
105 | fi | |||
|
|
106 | ||||
|
|
107 | # For Darwin, add options to specify how the application appears in the dock | |||
|
|
108 | if $darwin; then | |||
|
|
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |||
|
|
110 | fi | |||
|
|
111 | ||||
|
|
112 | # For Cygwin, switch paths to Windows format before running java | |||
|
|
113 | if $cygwin ; then | |||
|
|
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |||
|
|
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |||
|
|
116 | JAVACMD=`cygpath --unix "$JAVACMD"` | |||
|
|
117 | ||||
|
|
118 | # We build the pattern for arguments to be converted via cygpath | |||
|
|
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |||
|
|
120 | SEP="" | |||
|
|
121 | for dir in $ROOTDIRSRAW ; do | |||
|
|
122 | ROOTDIRS="$ROOTDIRS$SEP$dir" | |||
|
|
123 | SEP="|" | |||
|
|
124 | done | |||
|
|
125 | OURCYGPATTERN="(^($ROOTDIRS))" | |||
|
|
126 | # Add a user-defined pattern to the cygpath arguments | |||
|
|
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |||
|
|
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |||
|
|
129 | fi | |||
|
|
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh | |||
|
|
131 | i=0 | |||
|
|
132 | for arg in "$@" ; do | |||
|
|
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |||
|
|
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |||
|
|
135 | ||||
|
|
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |||
|
|
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |||
|
|
138 | else | |||
|
|
139 | eval `echo args$i`="\"$arg\"" | |||
|
|
140 | fi | |||
|
|
141 | i=$((i+1)) | |||
|
|
142 | done | |||
|
|
143 | case $i in | |||
|
|
144 | (0) set -- ;; | |||
|
|
145 | (1) set -- "$args0" ;; | |||
|
|
146 | (2) set -- "$args0" "$args1" ;; | |||
|
|
147 | (3) set -- "$args0" "$args1" "$args2" ;; | |||
|
|
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |||
|
|
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |||
|
|
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |||
|
|
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |||
|
|
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |||
|
|
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |||
|
|
154 | esac | |||
|
|
155 | fi | |||
|
|
156 | ||||
|
|
157 | # Escape application args | |||
|
|
158 | save () { | |||
|
|
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done | |||
|
|
160 | echo " " | |||
|
|
161 | } | |||
|
|
162 | APP_ARGS=$(save "$@") | |||
|
|
163 | ||||
|
|
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules | |||
|
|
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" | |||
|
|
166 | ||||
|
|
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong | |||
|
|
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then | |||
|
|
169 | cd "$(dirname "$0")" | |||
|
|
170 | fi | |||
|
|
171 | ||||
|
|
172 | exec "$JAVACMD" "$@" | |||
| @@ -0,0 +1,84 | |||||
|
|
1 | @if "%DEBUG%" == "" @echo off | |||
|
|
2 | @rem ########################################################################## | |||
|
|
3 | @rem | |||
|
|
4 | @rem Gradle startup script for Windows | |||
|
|
5 | @rem | |||
|
|
6 | @rem ########################################################################## | |||
|
|
7 | ||||
|
|
8 | @rem Set local scope for the variables with windows NT shell | |||
|
|
9 | if "%OS%"=="Windows_NT" setlocal | |||
|
|
10 | ||||
|
|
11 | set DIRNAME=%~dp0 | |||
|
|
12 | if "%DIRNAME%" == "" set DIRNAME=. | |||
|
|
13 | set APP_BASE_NAME=%~n0 | |||
|
|
14 | set APP_HOME=%DIRNAME% | |||
|
|
15 | ||||
|
|
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
|
|
17 | set DEFAULT_JVM_OPTS="-Xmx64m" | |||
|
|
18 | ||||
|
|
19 | @rem Find java.exe | |||
|
|
20 | if defined JAVA_HOME goto findJavaFromJavaHome | |||
|
|
21 | ||||
|
|
22 | set JAVA_EXE=java.exe | |||
|
|
23 | %JAVA_EXE% -version >NUL 2>&1 | |||
|
|
24 | if "%ERRORLEVEL%" == "0" goto init | |||
|
|
25 | ||||
|
|
26 | echo. | |||
|
|
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
|
|
28 | echo. | |||
|
|
29 | echo Please set the JAVA_HOME variable in your environment to match the | |||
|
|
30 | echo location of your Java installation. | |||
|
|
31 | ||||
|
|
32 | goto fail | |||
|
|
33 | ||||
|
|
34 | :findJavaFromJavaHome | |||
|
|
35 | set JAVA_HOME=%JAVA_HOME:"=% | |||
|
|
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |||
|
|
37 | ||||
|
|
38 | if exist "%JAVA_EXE%" goto init | |||
|
|
39 | ||||
|
|
40 | echo. | |||
|
|
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |||
|
|
42 | echo. | |||
|
|
43 | echo Please set the JAVA_HOME variable in your environment to match the | |||
|
|
44 | echo location of your Java installation. | |||
|
|
45 | ||||
|
|
46 | goto fail | |||
|
|
47 | ||||
|
|
48 | :init | |||
|
|
49 | @rem Get command-line arguments, handling Windows variants | |||
|
|
50 | ||||
|
|
51 | if not "%OS%" == "Windows_NT" goto win9xME_args | |||
|
|
52 | ||||
|
|
53 | :win9xME_args | |||
|
|
54 | @rem Slurp the command line arguments. | |||
|
|
55 | set CMD_LINE_ARGS= | |||
|
|
56 | set _SKIP=2 | |||
|
|
57 | ||||
|
|
58 | :win9xME_args_slurp | |||
|
|
59 | if "x%~1" == "x" goto execute | |||
|
|
60 | ||||
|
|
61 | set CMD_LINE_ARGS=%* | |||
|
|
62 | ||||
|
|
63 | :execute | |||
|
|
64 | @rem Setup the command line | |||
|
|
65 | ||||
|
|
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |||
|
|
67 | ||||
|
|
68 | @rem Execute Gradle | |||
|
|
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |||
|
|
70 | ||||
|
|
71 | :end | |||
|
|
72 | @rem End local scope for the variables with windows NT shell | |||
|
|
73 | if "%ERRORLEVEL%"=="0" goto mainEnd | |||
|
|
74 | ||||
|
|
75 | :fail | |||
|
|
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |||
|
|
77 | rem the _cmd.exe /c_ return code! | |||
|
|
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |||
|
|
79 | exit /b 1 | |||
|
|
80 | ||||
|
|
81 | :mainEnd | |||
|
|
82 | if "%OS%"=="Windows_NT" endlocal | |||
|
|
83 | ||||
|
|
84 | :omega | |||
| @@ -0,0 +1,10 | |||||
|
|
1 | HISTORY | |||
|
|
2 | ======= | |||
|
|
3 | ||||
|
|
4 | 1.0.0 | |||
|
|
5 | ----- | |||
|
|
6 | ||||
|
|
7 | First release, the port from legacy project, intorduces the following features | |||
|
|
8 | ||||
|
|
9 | - `security` - basic security model and concepts | |||
|
|
10 | - A resource-oriented web application framework No newline at end of file | |||
| @@ -0,0 +1,22 | |||||
|
|
1 | Copyright 2017-2019 Implab team | |||
|
|
2 | ||||
|
|
3 | Redistribution and use in source and binary forms, with or without | |||
|
|
4 | modification, are permitted provided that the following conditions are met: | |||
|
|
5 | ||||
|
|
6 | 1. Redistributions of source code must retain the above copyright notice, this | |||
|
|
7 | list of conditions and the following disclaimer. | |||
|
|
8 | ||||
|
|
9 | 2. Redistributions in binary form must reproduce the above copyright notice, | |||
|
|
10 | this list of conditions and the following disclaimer in the documentation | |||
|
|
11 | and/or other materials provided with the distribution. | |||
|
|
12 | ||||
|
|
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
|
|
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||
|
|
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
|
|
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |||
|
|
17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
|
|
18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
|
|
19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
|
|
20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
|
|
21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
|
|
22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. No newline at end of file | |||
| @@ -0,0 +1,477 | |||||
|
|
1 | { | |||
|
|
2 | "name": "@implab/web", | |||
|
|
3 | "version": "0.0.1-dev", | |||
|
|
4 | "lockfileVersion": 1, | |||
|
|
5 | "requires": true, | |||
|
|
6 | "dependencies": { | |||
|
|
7 | "@implab/core-amd": { | |||
|
|
8 | "version": "1.2.15", | |||
|
|
9 | "resolved": "https://registry.npmjs.org/@implab/core-amd/-/core-amd-1.2.15.tgz", | |||
|
|
10 | "integrity": "sha512-Vc5L9W/jz62R2fW1RnhPd6S503oztJLgddBGgNgJ4JjaBZt9P/Ym+98jAMkFbtCY3dX1RLM0SuI33hDPoG8Wgw==", | |||
|
|
11 | "dev": true | |||
|
|
12 | }, | |||
|
|
13 | "@types/node": { | |||
|
|
14 | "version": "11.9.4", | |||
|
|
15 | "resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.4.tgz", | |||
|
|
16 | "integrity": "sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA==", | |||
|
|
17 | "dev": true | |||
|
|
18 | }, | |||
|
|
19 | "@types/requirejs": { | |||
|
|
20 | "version": "2.1.31", | |||
|
|
21 | "resolved": "https://registry.npmjs.org/@types/requirejs/-/requirejs-2.1.31.tgz", | |||
|
|
22 | "integrity": "sha512-b2soeyuU76rMbcRJ4e0hEl0tbMhFwZeTC0VZnfuWlfGlk6BwWNsev6kFu/twKABPX29wkX84wU2o+cEJoXsiTw==", | |||
|
|
23 | "dev": true | |||
|
|
24 | }, | |||
|
|
25 | "@types/tape": { | |||
|
|
26 | "version": "4.2.33", | |||
|
|
27 | "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.33.tgz", | |||
|
|
28 | "integrity": "sha512-ltfyuY5BIkYlGuQfwqzTDT8f0q8Z5DGppvUnWGs39oqDmMd6/UWhNpX3ZMh/VYvfxs3rFGHMrLC/eGRdLiDGuw==", | |||
|
|
29 | "dev": true, | |||
|
|
30 | "requires": { | |||
|
|
31 | "@types/node": "*" | |||
|
|
32 | } | |||
|
|
33 | }, | |||
|
|
34 | "balanced-match": { | |||
|
|
35 | "version": "1.0.0", | |||
|
|
36 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", | |||
|
|
37 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", | |||
|
|
38 | "dev": true | |||
|
|
39 | }, | |||
|
|
40 | "brace-expansion": { | |||
|
|
41 | "version": "1.1.11", | |||
|
|
42 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", | |||
|
|
43 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", | |||
|
|
44 | "dev": true, | |||
|
|
45 | "requires": { | |||
|
|
46 | "balanced-match": "^1.0.0", | |||
|
|
47 | "concat-map": "0.0.1" | |||
|
|
48 | } | |||
|
|
49 | }, | |||
|
|
50 | "concat-map": { | |||
|
|
51 | "version": "0.0.1", | |||
|
|
52 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", | |||
|
|
53 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", | |||
|
|
54 | "dev": true | |||
|
|
55 | }, | |||
|
|
56 | "core-util-is": { | |||
|
|
57 | "version": "1.0.2", | |||
|
|
58 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | |||
|
|
59 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", | |||
|
|
60 | "dev": true | |||
|
|
61 | }, | |||
|
|
62 | "deep-equal": { | |||
|
|
63 | "version": "0.1.2", | |||
|
|
64 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", | |||
|
|
65 | "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", | |||
|
|
66 | "dev": true | |||
|
|
67 | }, | |||
|
|
68 | "define-properties": { | |||
|
|
69 | "version": "1.1.3", | |||
|
|
70 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", | |||
|
|
71 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", | |||
|
|
72 | "dev": true, | |||
|
|
73 | "requires": { | |||
|
|
74 | "object-keys": "^1.0.12" | |||
|
|
75 | }, | |||
|
|
76 | "dependencies": { | |||
|
|
77 | "object-keys": { | |||
|
|
78 | "version": "1.1.0", | |||
|
|
79 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", | |||
|
|
80 | "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", | |||
|
|
81 | "dev": true | |||
|
|
82 | } | |||
|
|
83 | } | |||
|
|
84 | }, | |||
|
|
85 | "defined": { | |||
|
|
86 | "version": "0.0.0", | |||
|
|
87 | "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", | |||
|
|
88 | "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", | |||
|
|
89 | "dev": true | |||
|
|
90 | }, | |||
|
|
91 | "dojo": { | |||
|
|
92 | "version": "1.15.0", | |||
|
|
93 | "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.15.0.tgz", | |||
|
|
94 | "integrity": "sha512-+1r5Nj1+iaHI8AxUadqsSp8wJMJM6sslr3INgWKhxUA0xHznBNY0htt38XLyheuy1G7oOwsh4X1An+Uzirj7Gw==", | |||
|
|
95 | "dev": true | |||
|
|
96 | }, | |||
|
|
97 | "duplexer": { | |||
|
|
98 | "version": "0.1.1", | |||
|
|
99 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", | |||
|
|
100 | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", | |||
|
|
101 | "dev": true | |||
|
|
102 | }, | |||
|
|
103 | "es-abstract": { | |||
|
|
104 | "version": "1.13.0", | |||
|
|
105 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", | |||
|
|
106 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", | |||
|
|
107 | "dev": true, | |||
|
|
108 | "requires": { | |||
|
|
109 | "es-to-primitive": "^1.2.0", | |||
|
|
110 | "function-bind": "^1.1.1", | |||
|
|
111 | "has": "^1.0.3", | |||
|
|
112 | "is-callable": "^1.1.4", | |||
|
|
113 | "is-regex": "^1.0.4", | |||
|
|
114 | "object-keys": "^1.0.12" | |||
|
|
115 | }, | |||
|
|
116 | "dependencies": { | |||
|
|
117 | "object-keys": { | |||
|
|
118 | "version": "1.1.0", | |||
|
|
119 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", | |||
|
|
120 | "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", | |||
|
|
121 | "dev": true | |||
|
|
122 | } | |||
|
|
123 | } | |||
|
|
124 | }, | |||
|
|
125 | "es-to-primitive": { | |||
|
|
126 | "version": "1.2.0", | |||
|
|
127 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", | |||
|
|
128 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", | |||
|
|
129 | "dev": true, | |||
|
|
130 | "requires": { | |||
|
|
131 | "is-callable": "^1.1.4", | |||
|
|
132 | "is-date-object": "^1.0.1", | |||
|
|
133 | "is-symbol": "^1.0.2" | |||
|
|
134 | } | |||
|
|
135 | }, | |||
|
|
136 | "faucet": { | |||
|
|
137 | "version": "0.0.1", | |||
|
|
138 | "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz", | |||
|
|
139 | "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=", | |||
|
|
140 | "dev": true, | |||
|
|
141 | "requires": { | |||
|
|
142 | "defined": "0.0.0", | |||
|
|
143 | "duplexer": "~0.1.1", | |||
|
|
144 | "minimist": "0.0.5", | |||
|
|
145 | "sprintf": "~0.1.3", | |||
|
|
146 | "tap-parser": "~0.4.0", | |||
|
|
147 | "tape": "~2.3.2", | |||
|
|
148 | "through2": "~0.2.3" | |||
|
|
149 | }, | |||
|
|
150 | "dependencies": { | |||
|
|
151 | "tape": { | |||
|
|
152 | "version": "2.3.3", | |||
|
|
153 | "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz", | |||
|
|
154 | "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=", | |||
|
|
155 | "dev": true, | |||
|
|
156 | "requires": { | |||
|
|
157 | "deep-equal": "~0.1.0", | |||
|
|
158 | "defined": "~0.0.0", | |||
|
|
159 | "inherits": "~2.0.1", | |||
|
|
160 | "jsonify": "~0.0.0", | |||
|
|
161 | "resumer": "~0.0.0", | |||
|
|
162 | "through": "~2.3.4" | |||
|
|
163 | } | |||
|
|
164 | } | |||
|
|
165 | } | |||
|
|
166 | }, | |||
|
|
167 | "for-each": { | |||
|
|
168 | "version": "0.3.3", | |||
|
|
169 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", | |||
|
|
170 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", | |||
|
|
171 | "dev": true, | |||
|
|
172 | "requires": { | |||
|
|
173 | "is-callable": "^1.1.3" | |||
|
|
174 | } | |||
|
|
175 | }, | |||
|
|
176 | "fs.realpath": { | |||
|
|
177 | "version": "1.0.0", | |||
|
|
178 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", | |||
|
|
179 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", | |||
|
|
180 | "dev": true | |||
|
|
181 | }, | |||
|
|
182 | "function-bind": { | |||
|
|
183 | "version": "1.1.1", | |||
|
|
184 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", | |||
|
|
185 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", | |||
|
|
186 | "dev": true | |||
|
|
187 | }, | |||
|
|
188 | "glob": { | |||
|
|
189 | "version": "7.1.3", | |||
|
|
190 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", | |||
|
|
191 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", | |||
|
|
192 | "dev": true, | |||
|
|
193 | "requires": { | |||
|
|
194 | "fs.realpath": "^1.0.0", | |||
|
|
195 | "inflight": "^1.0.4", | |||
|
|
196 | "inherits": "2", | |||
|
|
197 | "minimatch": "^3.0.4", | |||
|
|
198 | "once": "^1.3.0", | |||
|
|
199 | "path-is-absolute": "^1.0.0" | |||
|
|
200 | } | |||
|
|
201 | }, | |||
|
|
202 | "has": { | |||
|
|
203 | "version": "1.0.3", | |||
|
|
204 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", | |||
|
|
205 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", | |||
|
|
206 | "dev": true, | |||
|
|
207 | "requires": { | |||
|
|
208 | "function-bind": "^1.1.1" | |||
|
|
209 | } | |||
|
|
210 | }, | |||
|
|
211 | "has-symbols": { | |||
|
|
212 | "version": "1.0.0", | |||
|
|
213 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", | |||
|
|
214 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", | |||
|
|
215 | "dev": true | |||
|
|
216 | }, | |||
|
|
217 | "inflight": { | |||
|
|
218 | "version": "1.0.6", | |||
|
|
219 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", | |||
|
|
220 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", | |||
|
|
221 | "dev": true, | |||
|
|
222 | "requires": { | |||
|
|
223 | "once": "^1.3.0", | |||
|
|
224 | "wrappy": "1" | |||
|
|
225 | } | |||
|
|
226 | }, | |||
|
|
227 | "inherits": { | |||
|
|
228 | "version": "2.0.3", | |||
|
|
229 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | |||
|
|
230 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", | |||
|
|
231 | "dev": true | |||
|
|
232 | }, | |||
|
|
233 | "is-callable": { | |||
|
|
234 | "version": "1.1.4", | |||
|
|
235 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", | |||
|
|
236 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", | |||
|
|
237 | "dev": true | |||
|
|
238 | }, | |||
|
|
239 | "is-date-object": { | |||
|
|
240 | "version": "1.0.1", | |||
|
|
241 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", | |||
|
|
242 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", | |||
|
|
243 | "dev": true | |||
|
|
244 | }, | |||
|
|
245 | "is-regex": { | |||
|
|
246 | "version": "1.0.4", | |||
|
|
247 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", | |||
|
|
248 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", | |||
|
|
249 | "dev": true, | |||
|
|
250 | "requires": { | |||
|
|
251 | "has": "^1.0.1" | |||
|
|
252 | } | |||
|
|
253 | }, | |||
|
|
254 | "is-symbol": { | |||
|
|
255 | "version": "1.0.2", | |||
|
|
256 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", | |||
|
|
257 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", | |||
|
|
258 | "dev": true, | |||
|
|
259 | "requires": { | |||
|
|
260 | "has-symbols": "^1.0.0" | |||
|
|
261 | } | |||
|
|
262 | }, | |||
|
|
263 | "isarray": { | |||
|
|
264 | "version": "0.0.1", | |||
|
|
265 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | |||
|
|
266 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", | |||
|
|
267 | "dev": true | |||
|
|
268 | }, | |||
|
|
269 | "jsonify": { | |||
|
|
270 | "version": "0.0.0", | |||
|
|
271 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", | |||
|
|
272 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", | |||
|
|
273 | "dev": true | |||
|
|
274 | }, | |||
|
|
275 | "minimatch": { | |||
|
|
276 | "version": "3.0.4", | |||
|
|
277 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", | |||
|
|
278 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", | |||
|
|
279 | "dev": true, | |||
|
|
280 | "requires": { | |||
|
|
281 | "brace-expansion": "^1.1.7" | |||
|
|
282 | } | |||
|
|
283 | }, | |||
|
|
284 | "minimist": { | |||
|
|
285 | "version": "0.0.5", | |||
|
|
286 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", | |||
|
|
287 | "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=", | |||
|
|
288 | "dev": true | |||
|
|
289 | }, | |||
|
|
290 | "object-inspect": { | |||
|
|
291 | "version": "1.6.0", | |||
|
|
292 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", | |||
|
|
293 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", | |||
|
|
294 | "dev": true | |||
|
|
295 | }, | |||
|
|
296 | "object-keys": { | |||
|
|
297 | "version": "0.4.0", | |||
|
|
298 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", | |||
|
|
299 | "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", | |||
|
|
300 | "dev": true | |||
|
|
301 | }, | |||
|
|
302 | "once": { | |||
|
|
303 | "version": "1.4.0", | |||
|
|
304 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", | |||
|
|
305 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", | |||
|
|
306 | "dev": true, | |||
|
|
307 | "requires": { | |||
|
|
308 | "wrappy": "1" | |||
|
|
309 | } | |||
|
|
310 | }, | |||
|
|
311 | "path-is-absolute": { | |||
|
|
312 | "version": "1.0.1", | |||
|
|
313 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", | |||
|
|
314 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", | |||
|
|
315 | "dev": true | |||
|
|
316 | }, | |||
|
|
317 | "path-parse": { | |||
|
|
318 | "version": "1.0.6", | |||
|
|
319 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", | |||
|
|
320 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", | |||
|
|
321 | "dev": true | |||
|
|
322 | }, | |||
|
|
323 | "readable-stream": { | |||
|
|
324 | "version": "1.1.14", | |||
|
|
325 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", | |||
|
|
326 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", | |||
|
|
327 | "dev": true, | |||
|
|
328 | "requires": { | |||
|
|
329 | "core-util-is": "~1.0.0", | |||
|
|
330 | "inherits": "~2.0.1", | |||
|
|
331 | "isarray": "0.0.1", | |||
|
|
332 | "string_decoder": "~0.10.x" | |||
|
|
333 | } | |||
|
|
334 | }, | |||
|
|
335 | "requirejs": { | |||
|
|
336 | "version": "2.3.6", | |||
|
|
337 | "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", | |||
|
|
338 | "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", | |||
|
|
339 | "dev": true | |||
|
|
340 | }, | |||
|
|
341 | "resolve": { | |||
|
|
342 | "version": "1.10.0", | |||
|
|
343 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", | |||
|
|
344 | "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", | |||
|
|
345 | "dev": true, | |||
|
|
346 | "requires": { | |||
|
|
347 | "path-parse": "^1.0.6" | |||
|
|
348 | } | |||
|
|
349 | }, | |||
|
|
350 | "resumer": { | |||
|
|
351 | "version": "0.0.0", | |||
|
|
352 | "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", | |||
|
|
353 | "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", | |||
|
|
354 | "dev": true, | |||
|
|
355 | "requires": { | |||
|
|
356 | "through": "~2.3.4" | |||
|
|
357 | } | |||
|
|
358 | }, | |||
|
|
359 | "sprintf": { | |||
|
|
360 | "version": "0.1.5", | |||
|
|
361 | "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", | |||
|
|
362 | "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=", | |||
|
|
363 | "dev": true | |||
|
|
364 | }, | |||
|
|
365 | "string.prototype.trim": { | |||
|
|
366 | "version": "1.1.2", | |||
|
|
367 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", | |||
|
|
368 | "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", | |||
|
|
369 | "dev": true, | |||
|
|
370 | "requires": { | |||
|
|
371 | "define-properties": "^1.1.2", | |||
|
|
372 | "es-abstract": "^1.5.0", | |||
|
|
373 | "function-bind": "^1.0.2" | |||
|
|
374 | } | |||
|
|
375 | }, | |||
|
|
376 | "string_decoder": { | |||
|
|
377 | "version": "0.10.31", | |||
|
|
378 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", | |||
|
|
379 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", | |||
|
|
380 | "dev": true | |||
|
|
381 | }, | |||
|
|
382 | "tap-parser": { | |||
|
|
383 | "version": "0.4.3", | |||
|
|
384 | "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz", | |||
|
|
385 | "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=", | |||
|
|
386 | "dev": true, | |||
|
|
387 | "requires": { | |||
|
|
388 | "inherits": "~2.0.1", | |||
|
|
389 | "readable-stream": "~1.1.11" | |||
|
|
390 | } | |||
|
|
391 | }, | |||
|
|
392 | "tape": { | |||
|
|
393 | "version": "4.10.1", | |||
|
|
394 | "resolved": "https://registry.npmjs.org/tape/-/tape-4.10.1.tgz", | |||
|
|
395 | "integrity": "sha512-G0DywYV1jQeY3axeYnXUOt6ktnxS9OPJh97FGR3nrua8lhWi1zPflLxcAHavZ7Jf3qUfY7cxcVIVFa4mY2IY1w==", | |||
|
|
396 | "dev": true, | |||
|
|
397 | "requires": { | |||
|
|
398 | "deep-equal": "~1.0.1", | |||
|
|
399 | "defined": "~1.0.0", | |||
|
|
400 | "for-each": "~0.3.3", | |||
|
|
401 | "function-bind": "~1.1.1", | |||
|
|
402 | "glob": "~7.1.3", | |||
|
|
403 | "has": "~1.0.3", | |||
|
|
404 | "inherits": "~2.0.3", | |||
|
|
405 | "minimist": "~1.2.0", | |||
|
|
406 | "object-inspect": "~1.6.0", | |||
|
|
407 | "resolve": "~1.10.0", | |||
|
|
408 | "resumer": "~0.0.0", | |||
|
|
409 | "string.prototype.trim": "~1.1.2", | |||
|
|
410 | "through": "~2.3.8" | |||
|
|
411 | }, | |||
|
|
412 | "dependencies": { | |||
|
|
413 | "deep-equal": { | |||
|
|
414 | "version": "1.0.1", | |||
|
|
415 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", | |||
|
|
416 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", | |||
|
|
417 | "dev": true | |||
|
|
418 | }, | |||
|
|
419 | "defined": { | |||
|
|
420 | "version": "1.0.0", | |||
|
|
421 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", | |||
|
|
422 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", | |||
|
|
423 | "dev": true | |||
|
|
424 | }, | |||
|
|
425 | "minimist": { | |||
|
|
426 | "version": "1.2.0", | |||
|
|
427 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", | |||
|
|
428 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", | |||
|
|
429 | "dev": true | |||
|
|
430 | } | |||
|
|
431 | } | |||
|
|
432 | }, | |||
|
|
433 | "through": { | |||
|
|
434 | "version": "2.3.8", | |||
|
|
435 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", | |||
|
|
436 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", | |||
|
|
437 | "dev": true | |||
|
|
438 | }, | |||
|
|
439 | "through2": { | |||
|
|
440 | "version": "0.2.3", | |||
|
|
441 | "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", | |||
|
|
442 | "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", | |||
|
|
443 | "dev": true, | |||
|
|
444 | "requires": { | |||
|
|
445 | "readable-stream": "~1.1.9", | |||
|
|
446 | "xtend": "~2.1.1" | |||
|
|
447 | } | |||
|
|
448 | }, | |||
|
|
449 | "tslib": { | |||
|
|
450 | "version": "1.9.3", | |||
|
|
451 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", | |||
|
|
452 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", | |||
|
|
453 | "dev": true | |||
|
|
454 | }, | |||
|
|
455 | "typescript": { | |||
|
|
456 | "version": "3.3.3", | |||
|
|
457 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3.tgz", | |||
|
|
458 | "integrity": "sha512-Y21Xqe54TBVp+VDSNbuDYdGw0BpoR/Q6wo/+35M8PAU0vipahnyduJWirxxdxjsAkS7hue53x2zp8gz7F05u0A==", | |||
|
|
459 | "dev": true | |||
|
|
460 | }, | |||
|
|
461 | "wrappy": { | |||
|
|
462 | "version": "1.0.2", | |||
|
|
463 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", | |||
|
|
464 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", | |||
|
|
465 | "dev": true | |||
|
|
466 | }, | |||
|
|
467 | "xtend": { | |||
|
|
468 | "version": "2.1.2", | |||
|
|
469 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", | |||
|
|
470 | "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", | |||
|
|
471 | "dev": true, | |||
|
|
472 | "requires": { | |||
|
|
473 | "object-keys": "~0.4.0" | |||
|
|
474 | } | |||
|
|
475 | } | |||
|
|
476 | } | |||
|
|
477 | } | |||
| @@ -0,0 +1,25 | |||||
|
|
1 | { | |||
|
|
2 | "name": "${packageName}", | |||
|
|
3 | "version": "${version}", | |||
|
|
4 | "description": "${description}", | |||
|
|
5 | "main": "main.js", | |||
|
|
6 | "keywords": [ | |||
|
|
7 | "di", | |||
|
|
8 | "ioc", | |||
|
|
9 | "logging", | |||
|
|
10 | "template engine", | |||
|
|
11 | "dependency injection" | |||
|
|
12 | ], | |||
|
|
13 | "author": "${author}", | |||
|
|
14 | "license": "${license}", | |||
|
|
15 | "repository": "$repository", | |||
|
|
16 | "publishConfig": { | |||
|
|
17 | "access": "public" | |||
|
|
18 | }, | |||
|
|
19 | "peerDependencies": { | |||
|
|
20 | "dojo": "^1.10.0", | |||
|
|
21 | "@implab/core-amd": "^1.2.0" | |||
|
|
22 | }, | |||
|
|
23 | "module": "${jsmodule}", | |||
|
|
24 | "target": "${target}" | |||
|
|
25 | } No newline at end of file | |||
| @@ -0,0 +1,37 | |||||
|
|
1 | { | |||
|
|
2 | "name": "@implab/web", | |||
|
|
3 | "version": "0.0.1-dev", | |||
|
|
4 | "description": "Simple web framework", | |||
|
|
5 | "main": "main.js", | |||
|
|
6 | "keywords": [ | |||
|
|
7 | "di", | |||
|
|
8 | "ioc", | |||
|
|
9 | "logging", | |||
|
|
10 | "template engine", | |||
|
|
11 | "dependency injection" | |||
|
|
12 | ], | |||
|
|
13 | "author": "Implab team", | |||
|
|
14 | "license": "BSD-2-Clause", | |||
|
|
15 | "repository": "https://bitbucket.org/implab/implabjs", | |||
|
|
16 | "publishConfig": { | |||
|
|
17 | "access": "public" | |||
|
|
18 | }, | |||
|
|
19 | "peerDependencies": { | |||
|
|
20 | "dojo": "^1.10.0", | |||
|
|
21 | "@implab/core-amd": "^1.2.15", | |||
|
|
22 | "tslib": "latest" | |||
|
|
23 | }, | |||
|
|
24 | "devDependencies": { | |||
|
|
25 | "@types/node": "latest", | |||
|
|
26 | "@types/requirejs": "latest", | |||
|
|
27 | "@types/tape": "latest", | |||
|
|
28 | "@implab/core-amd": "^1.2.15", | |||
|
|
29 | "dojo": "^1.10.0", | |||
|
|
30 | "faucet": "latest", | |||
|
|
31 | "requirejs": "latest", | |||
|
|
32 | "tape": "^4.9.2", | |||
|
|
33 | "tslib": "latest", | |||
|
|
34 | "typescript": "latest" | |||
|
|
35 | }, | |||
|
|
36 | "types": "main.d.ts" | |||
|
|
37 | } | |||
| @@ -0,0 +1,27 | |||||
|
|
1 | # Implabjs-core | |||
|
|
2 | ||||
|
|
3 | Набор стандартных библиотек для создания приложений со сложным функционалом. | |||
|
|
4 | Данную библиотеку можно использовать как для разработки приложений, которые | |||
|
|
5 | будут работать в среде браузеров, так и в серверных средах. | |||
|
|
6 | ||||
|
|
7 | Библиотека написана на TypeScript, некоторая часть на JavaScript, но постепенно | |||
|
|
8 | планируется перейти полностью на использование TypeScript | |||
|
|
9 | ||||
|
|
10 | Более подробная документация доступна по ссылке: <https://bitbucket.org/implab/implabjs-core/src/default/docs/ru/> | |||
|
|
11 | ||||
|
|
12 | ## Основные компоненты | |||
|
|
13 | ||||
|
|
14 | ### DI | |||
|
|
15 | ||||
|
|
16 | Контейнер для внедрения зависимостей, позволяет гибко описывать структуру | |||
|
|
17 | приложения и создавать слабосвязанные компоненты. | |||
|
|
18 | ||||
|
|
19 | ### LOG | |||
|
|
20 | ||||
|
|
21 | Средства журналирования похожие на JLog, позволяют эффективно вести журнал | |||
|
|
22 | выполнения программы. | |||
|
|
23 | ||||
|
|
24 | ### Cancellations | |||
|
|
25 | ||||
|
|
26 | Специальные маркеры для отмены асинхронных операций, по аналогии с .NET | |||
|
|
27 | CancelationToken. | |||
| @@ -0,0 +1,15 | |||||
|
|
1 | /* | |||
|
|
2 | * This settings file was generated by the Gradle 'init' task. | |||
|
|
3 | * | |||
|
|
4 | * The settings file is used to specify which projects to include in your build. | |||
|
|
5 | * In a single project build this file can be empty or even removed. | |||
|
|
6 | * | |||
|
|
7 | * Detailed information about configuring a multi-project build in Gradle can be found | |||
|
|
8 | * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html | |||
|
|
9 | */ | |||
|
|
10 | ||||
|
|
11 | // To declare projects as part of a multi-project build use the 'include' method | |||
|
|
12 | ||||
|
|
13 | //include 'sub-project-name' | |||
|
|
14 | ||||
|
|
15 | rootProject.name = 'web' No newline at end of file | |||
| @@ -0,0 +1,167 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "dojo/_base/lang", | |||
|
|
4 | "dojo/when", | |||
|
|
5 | "cluster", | |||
|
|
6 | "os", | |||
|
|
7 | "implab/safe", | |||
|
|
8 | "./HttpResponse", | |||
|
|
9 | "./BaseResponse", | |||
|
|
10 | "dojo/Deferred", | |||
|
|
11 | "./HttpException", | |||
|
|
12 | "@implab/core/log/trace!"], | |||
|
|
13 | function (declare, lang, when, cluster, os, safe, HttpResponse, BaseResponse, Deferred, HttpException, trace) { | |||
|
|
14 | return declare(null, { | |||
|
|
15 | _container: null, | |||
|
|
16 | _serverPort: null, | |||
|
|
17 | _bindAddr: null, | |||
|
|
18 | ||||
|
|
19 | _useCluster: null, | |||
|
|
20 | ||||
|
|
21 | _requestConfig: null, | |||
|
|
22 | _restartFailedWorkers: null, | |||
|
|
23 | ||||
|
|
24 | // модули, обрабатывающие запрос. | |||
|
|
25 | _modules: null, | |||
|
|
26 | _handlers: null, | |||
|
|
27 | ||||
|
|
28 | constructor: function (options) { | |||
|
|
29 | safe.argumentNotNull(options, "options"); | |||
|
|
30 | safe.argumentNotNull(options.container, "options.container"); | |||
|
|
31 | safe.argumentNotNull(options.serverPort, "options.serverPort"); | |||
|
|
32 | safe.argumentNotNull(options.useCluster, "options.useCluster"); | |||
|
|
33 | safe.argumentNotEmptyString(options.bindAddr, "options.bindAddr"); | |||
|
|
34 | safe.argumentNotEmptyString(options.requestConfig, "options.requestConfig"); | |||
|
|
35 | ||||
|
|
36 | this.options = options || {}; | |||
|
|
37 | this._modules = []; | |||
|
|
38 | ||||
|
|
39 | this._container = options.container; | |||
|
|
40 | ||||
|
|
41 | this._serverPort = options.serverPort; | |||
|
|
42 | this._bindAddr = options.bindAddr; | |||
|
|
43 | this._useCluster = options.useCluster; | |||
|
|
44 | this._restartFailedWorkers = options.restartFailedWorkers; | |||
|
|
45 | ||||
|
|
46 | this._requestConfig = options.requestConfig; | |||
|
|
47 | ||||
|
|
48 | this._container.getService("httpHandlers").forEach(handler => { | |||
|
|
49 | this.handle(handler); | |||
|
|
50 | }); | |||
|
|
51 | }, | |||
|
|
52 | ||||
|
|
53 | start: function () { | |||
|
|
54 | let me = this; | |||
|
|
55 | const numCPUs = os.cpus().length; | |||
|
|
56 | if (cluster.isMaster && me._useCluster) { | |||
|
|
57 | // Fork workers. | |||
|
|
58 | for (let i = 0; i < numCPUs; i++) { | |||
|
|
59 | cluster.fork(); | |||
|
|
60 | } | |||
|
|
61 | ||||
|
|
62 | cluster.on('exit', function (worker, code, signal) { | |||
|
|
63 | if(me._restartFailedWorkers){ | |||
|
|
64 | trace.log("worker {0} died. Signal {1}. Restarting ...", worker.process.pid, signal); | |||
|
|
65 | cluster.fork(); | |||
|
|
66 | } else { | |||
|
|
67 | trace.log("worker {0} died.", worker.process.pid); | |||
|
|
68 | } | |||
|
|
69 | }); | |||
|
|
70 | } else { | |||
|
|
71 | // Workers can share any TCP connection | |||
|
|
72 | // In this case it is an HTTP server | |||
|
|
73 | this.listen(this._serverPort, this._bindAddr); | |||
|
|
74 | } | |||
|
|
75 | }, | |||
|
|
76 | ||||
|
|
77 | listen: function (port, host) { | |||
|
|
78 | this._host = host; | |||
|
|
79 | this._port = port; | |||
|
|
80 | ||||
|
|
81 | this._createServer(this.options, lang.hitch(this, "_handler")).listen(port, host, lang.hitch(this, "_listening")); | |||
|
|
82 | }, | |||
|
|
83 | ||||
|
|
84 | handle: function (module) { | |||
|
|
85 | if (module instanceof Function) | |||
|
|
86 | this._modules.push(module); | |||
|
|
87 | else if (module.invoke instanceof Function) | |||
|
|
88 | this._modules.push(function (req, next) { | |||
|
|
89 | return module.invoke(req, next); | |||
|
|
90 | }); | |||
|
|
91 | else | |||
|
|
92 | throw "module shoud be a function or should have an invoke method"; | |||
|
|
93 | }, | |||
|
|
94 | ||||
|
|
95 | _createServer: function () { | |||
|
|
96 | throw "NOT IMPLEMENTED"; | |||
|
|
97 | }, | |||
|
|
98 | ||||
|
|
99 | _createRequest: function (container, req, res) { | |||
|
|
100 | return container.configure(this._requestConfig) | |||
|
|
101 | .then(function () { | |||
|
|
102 | let httpRequest = container.getService("httpRequest"); | |||
|
|
103 | httpRequest.init(req, res); | |||
|
|
104 | return httpRequest; | |||
|
|
105 | }); | |||
|
|
106 | }, | |||
|
|
107 | ||||
|
|
108 | //handler function to pass to the approperate server (like node.http) | |||
|
|
109 | _handler: function (req, res) { | |||
|
|
110 | let i = 0; | |||
|
|
111 | let me = this; | |||
|
|
112 | ||||
|
|
113 | let requestContainer = this._container.createChildContainer(); | |||
|
|
114 | ||||
|
|
115 | when(this._createRequest(requestContainer, req, res), function (httpRequest) { | |||
|
|
116 | let next = function () { | |||
|
|
117 | if (i < me._modules.length) { | |||
|
|
118 | let module = me._modules[i]; | |||
|
|
119 | i++; | |||
|
|
120 | try { | |||
|
|
121 | return when(module(httpRequest, next)); | |||
|
|
122 | } catch (err) { | |||
|
|
123 | let d = new Deferred(); | |||
|
|
124 | d.reject(err); | |||
|
|
125 | return d; | |||
|
|
126 | } | |||
|
|
127 | } | |||
|
|
128 | }; | |||
|
|
129 | ||||
|
|
130 | when(next(), function (result) { | |||
|
|
131 | if (!result) | |||
|
|
132 | throw "no response is provided, this is a serious bug"; | |||
|
|
133 | ||||
|
|
134 | if (result instanceof BaseResponse) { | |||
|
|
135 | result.send(res); | |||
|
|
136 | } else { | |||
|
|
137 | let httpResp = new HttpResponse(); | |||
|
|
138 | httpResp.content = "BUG: " + result.toString(); | |||
|
|
139 | httpResp.send(res); | |||
|
|
140 | } | |||
|
|
141 | requestContainer.dispose(); | |||
|
|
142 | }).then(null, function (err) { | |||
|
|
143 | if (res.finished) { | |||
|
|
144 | trace.log("caught exception after the response is sent: {0}", err); | |||
|
|
145 | return; | |||
|
|
146 | } | |||
|
|
147 | let httpResp; | |||
|
|
148 | if (err instanceof HttpException) | |||
|
|
149 | httpResp = new HttpResponse(err.message, { | |||
|
|
150 | statusCode: err.code, | |||
|
|
151 | headers: err.headers | |||
|
|
152 | }); | |||
|
|
153 | else | |||
|
|
154 | httpResp = new HttpResponse(err.toString(), { | |||
|
|
155 | statusCode: 500 | |||
|
|
156 | }); | |||
|
|
157 | httpResp.send(res); | |||
|
|
158 | requestContainer.dispose(); | |||
|
|
159 | }); | |||
|
|
160 | }); | |||
|
|
161 | }, | |||
|
|
162 | _listening: function () { | |||
|
|
163 | trace.log("Listening {0}:{1}", this._host, this._port); | |||
|
|
164 | }, | |||
|
|
165 | ||||
|
|
166 | }); | |||
|
|
167 | }); No newline at end of file | |||
| @@ -0,0 +1,7 | |||||
|
|
1 | define([ "dojo/_base/declare"], function(declare) { | |||
|
|
2 | return declare(null, { | |||
|
|
3 | send : function(/*serverResponse*/) { | |||
|
|
4 | throw "NOT IMPLEMENTED"; | |||
|
|
5 | } | |||
|
|
6 | }); | |||
|
|
7 | }); No newline at end of file | |||
| @@ -0,0 +1,22 | |||||
|
|
1 | define(["dojo/_base/declare", "dojo/when", "./BaseResponse", "./ModelResponse"],function(declare,when, BaseResponse, ModelResponse) { | |||
|
|
2 | return declare(null,{ | |||
|
|
3 | invoke: function(httpRequest, next) { | |||
|
|
4 | return when(next(), function(result) { | |||
|
|
5 | if (!(result instanceof BaseResponse) ){ | |||
|
|
6 | result = new ModelResponse(result); | |||
|
|
7 | } | |||
|
|
8 | ||||
|
|
9 | if (!(result instanceof ModelResponse)) | |||
|
|
10 | return result; | |||
|
|
11 | ||||
|
|
12 | result.presenter = { | |||
|
|
13 | present: JSON.stringify, | |||
|
|
14 | contentType: "application/json; charset=utf-8" | |||
|
|
15 | }; | |||
|
|
16 | ||||
|
|
17 | // TODO select presenter and assing it to result.presenter | |||
|
|
18 | return result; | |||
|
|
19 | }); | |||
|
|
20 | } | |||
|
|
21 | }); | |||
|
|
22 | }); No newline at end of file | |||
| @@ -0,0 +1,206 | |||||
|
|
1 | define([ "dojo/_base/declare", "dojo/_base/lang" ], function(declare, lang) { | |||
|
|
2 | let cls = declare(null, { | |||
|
|
3 | type : null, | |||
|
|
4 | subtype : null, | |||
|
|
5 | parameters: null, | |||
|
|
6 | ||||
|
|
7 | constructor: function(media,parameters) { | |||
|
|
8 | if (!media) | |||
|
|
9 | throw "A media must be specified"; | |||
|
|
10 | media = media.toString(); | |||
|
|
11 | let parts = media.match(/^([a-zA-Z-]+)\/([a-zA-Z\-+]+)$/); | |||
|
|
12 | if(!parts) | |||
|
|
13 | throw "An invalid media type supplied"; | |||
|
|
14 | this.type = parts[1]; | |||
|
|
15 | this.subtype = parts[2]; | |||
|
|
16 | this.parameters = parameters || {}; | |||
|
|
17 | }, | |||
|
|
18 | ||||
|
|
19 | toString : function() { | |||
|
|
20 | let res = [this.type,'/',this.subtype]; | |||
|
|
21 | for(var p in this.parameters) { | |||
|
|
22 | res.push('; '); | |||
|
|
23 | res.push(p); | |||
|
|
24 | res.push('='); | |||
|
|
25 | res.push(this._escapeValue(this.parameters[p])); | |||
|
|
26 | } | |||
|
|
27 | ||||
|
|
28 | return res.join(''); | |||
|
|
29 | }, | |||
|
|
30 | ||||
|
|
31 | _escapeValue : function(value) { | |||
|
|
32 | if (value) { | |||
|
|
33 | value = value.toString(); | |||
|
|
34 | if(value.match(/[()<>@,:;\\".[\]]/)) | |||
|
|
35 | return '"' + value.replace(/[()<>@,:;\\".[\]]/g, function(x) { return "\\"+ x; } ) + '"'; | |||
|
|
36 | } | |||
|
|
37 | return value; | |||
|
|
38 | } | |||
|
|
39 | ||||
|
|
40 | }); | |||
|
|
41 | ||||
|
|
42 | let parseSpace = function(text,start) { | |||
|
|
43 | for(var i = start; i < text.length; i++) { | |||
|
|
44 | if(!text[i].match(/\s/)) | |||
|
|
45 | break; | |||
|
|
46 | } | |||
|
|
47 | return { | |||
|
|
48 | pos: i | |||
|
|
49 | }; | |||
|
|
50 | }; | |||
|
|
51 | ||||
|
|
52 | let parseToken = function(text,start,required) { | |||
|
|
53 | let token = []; | |||
|
|
54 | for(var i=start; i< text.length; i++) { | |||
|
|
55 | let char = text[i]; | |||
|
|
56 | if (!char.match(/[\w-]/)) | |||
|
|
57 | break; | |||
|
|
58 | token.push(char); | |||
|
|
59 | } | |||
|
|
60 | ||||
|
|
61 | if (required && token.length == 0) { | |||
|
|
62 | if (i == text.length) | |||
|
|
63 | throw new Error("Unexpected end of line"); | |||
|
|
64 | else | |||
|
|
65 | throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[i], pos: i}); | |||
|
|
66 | } | |||
|
|
67 | ||||
|
|
68 | return { | |||
|
|
69 | value : token.join(''), | |||
|
|
70 | pos : i | |||
|
|
71 | }; | |||
|
|
72 | }; | |||
|
|
73 | ||||
|
|
74 | ||||
|
|
75 | let parseMedia = function(text,start) { | |||
|
|
76 | let type, subtype; | |||
|
|
77 | let t = parseToken(text,start,true); | |||
|
|
78 | ||||
|
|
79 | type = t.value; | |||
|
|
80 | start = t.pos; | |||
|
|
81 | ||||
|
|
82 | if (text[start] != '/') | |||
|
|
83 | throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[start], pos: start}); | |||
|
|
84 | start++; | |||
|
|
85 | ||||
|
|
86 | t = parseToken(text,start,true); | |||
|
|
87 | subtype = t.value; | |||
|
|
88 | start = t.pos; | |||
|
|
89 | ||||
|
|
90 | return { | |||
|
|
91 | value: { | |||
|
|
92 | type : type, | |||
|
|
93 | subtype: subtype | |||
|
|
94 | }, | |||
|
|
95 | pos : start | |||
|
|
96 | }; | |||
|
|
97 | }; | |||
|
|
98 | ||||
|
|
99 | let parseLiteral = function(text,pos,required) { | |||
|
|
100 | let data = []; | |||
|
|
101 | let escape, stop; | |||
|
|
102 | for(var i=pos; (i < text.length) && !stop; i++) { | |||
|
|
103 | if (escape) { | |||
|
|
104 | data.push(text[i]); | |||
|
|
105 | escape = false; | |||
|
|
106 | } else { | |||
|
|
107 | switch(text[i]) { | |||
|
|
108 | ||||
|
|
109 | case '"': | |||
|
|
110 | if (pos != i) | |||
|
|
111 | stop = true; | |||
|
|
112 | break; | |||
|
|
113 | case '\\': | |||
|
|
114 | escape = true; | |||
|
|
115 | break; | |||
|
|
116 | default: | |||
|
|
117 | if (pos == i) { | |||
|
|
118 | stop = true; | |||
|
|
119 | i--; | |||
|
|
120 | } else { | |||
|
|
121 | data.push(text[i]); | |||
|
|
122 | } | |||
|
|
123 | } | |||
|
|
124 | } | |||
|
|
125 | } | |||
|
|
126 | ||||
|
|
127 | if(required && data.length == 0) | |||
|
|
128 | new lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[i], pos: i}); | |||
|
|
129 | ||||
|
|
130 | return { | |||
|
|
131 | value : data.join(''), | |||
|
|
132 | pos : i | |||
|
|
133 | }; | |||
|
|
134 | }; | |||
|
|
135 | ||||
|
|
136 | let parseParam = function(text,pos) { | |||
|
|
137 | let t,name,value; | |||
|
|
138 | t = parseToken(text,pos,true); | |||
|
|
139 | ||||
|
|
140 | name = t.value; | |||
|
|
141 | pos = t.pos; | |||
|
|
142 | ||||
|
|
143 | t = parseSpace(text,pos); | |||
|
|
144 | pos = t.pos; | |||
|
|
145 | ||||
|
|
146 | if (text[pos] != '=') | |||
|
|
147 | throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); | |||
|
|
148 | pos++; | |||
|
|
149 | ||||
|
|
150 | t = parseSpace(text,pos); | |||
|
|
151 | pos = t.pos; | |||
|
|
152 | ||||
|
|
153 | t = parseToken(text,pos,false); | |||
|
|
154 | if (t.pos != pos) { | |||
|
|
155 | value = t.value; | |||
|
|
156 | pos = t.pos; | |||
|
|
157 | } else { | |||
|
|
158 | t = parseLiteral(text,pos,false); | |||
|
|
159 | if (t.pos == pos) | |||
|
|
160 | throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); | |||
|
|
161 | pos = t.pos; | |||
|
|
162 | value = t.value; | |||
|
|
163 | } | |||
|
|
164 | ||||
|
|
165 | return { | |||
|
|
166 | value : { | |||
|
|
167 | name : name, | |||
|
|
168 | value : value | |||
|
|
169 | }, | |||
|
|
170 | pos : pos | |||
|
|
171 | }; | |||
|
|
172 | }; | |||
|
|
173 | ||||
|
|
174 | cls.parse = function(text) { | |||
|
|
175 | let t,pos = 0, media, params = {}; | |||
|
|
176 | t = parseMedia(text,pos); | |||
|
|
177 | media = t.value; | |||
|
|
178 | pos = t.pos; | |||
|
|
179 | ||||
|
|
180 | ||||
|
|
181 | while(pos < text.length) { | |||
|
|
182 | t = parseSpace(text,pos); | |||
|
|
183 | pos = t.pos; | |||
|
|
184 | ||||
|
|
185 | if (pos < text.length) { | |||
|
|
186 | if(text[pos] == ';') { | |||
|
|
187 | pos ++; | |||
|
|
188 | t = parseSpace(text,pos); | |||
|
|
189 | pos = t.pos; | |||
|
|
190 | ||||
|
|
191 | t = parseParam(text,pos); | |||
|
|
192 | ||||
|
|
193 | params[t.value.name] = t.value.value; | |||
|
|
194 | pos = t.pos; | |||
|
|
195 | ||||
|
|
196 | } else { | |||
|
|
197 | throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); | |||
|
|
198 | } | |||
|
|
199 | } | |||
|
|
200 | } | |||
|
|
201 | ||||
|
|
202 | return new cls( media.type + '/' + media.subtype, params ); | |||
|
|
203 | }; | |||
|
|
204 | ||||
|
|
205 | return cls; | |||
|
|
206 | }); No newline at end of file | |||
| @@ -0,0 +1,238 | |||||
|
|
1 | /** | |||
|
|
2 | * | |||
|
|
3 | */ | |||
|
|
4 | define(["dojo/_base/declare", "dojo/_base/lang", "implab/safe"], function (declare, lang, safe) { | |||
|
|
5 | ||||
|
|
6 | ||||
|
|
7 | var formats = { | |||
|
|
8 | "base64+json": { | |||
|
|
9 | encode: function (data) { | |||
|
|
10 | return new Buffer(JSON.stringify(data)).toString('base64'); | |||
|
|
11 | }, | |||
|
|
12 | decode: function (data) { | |||
|
|
13 | try { | |||
|
|
14 | return JSON.parse(new Buffer(data, 'base64').toString()); | |||
|
|
15 | } catch (err) { | |||
|
|
16 | return null; | |||
|
|
17 | } | |||
|
|
18 | } | |||
|
|
19 | }, | |||
|
|
20 | "base64": { | |||
|
|
21 | encode: function (data) { | |||
|
|
22 | if (!safe.isPrimitive(data)) | |||
|
|
23 | throw new Error("Can'n serialize a complex data"); | |||
|
|
24 | return new Buffer(data).toString('base64'); | |||
|
|
25 | }, | |||
|
|
26 | decode: function (data) { | |||
|
|
27 | return new Buffer(data, 'base64').toString(); | |||
|
|
28 | }, | |||
|
|
29 | }, | |||
|
|
30 | "simple": { | |||
|
|
31 | encode: function (data) { | |||
|
|
32 | if (!safe.isPrimitive(data)) | |||
|
|
33 | throw new Error("Can'n serialize a complex data"); | |||
|
|
34 | return safe.isNull(data) ? "" : data.toString(); | |||
|
|
35 | }, | |||
|
|
36 | decode: function (data) { | |||
|
|
37 | return data; | |||
|
|
38 | } | |||
|
|
39 | } | |||
|
|
40 | }; | |||
|
|
41 | ||||
|
|
42 | let args = { | |||
|
|
43 | secure: false, | |||
|
|
44 | httpOnly: false, | |||
|
|
45 | path: null, | |||
|
|
46 | domain: null, | |||
|
|
47 | maxAge: null, | |||
|
|
48 | expires: null, | |||
|
|
49 | extension: null, | |||
|
|
50 | format: null | |||
|
|
51 | }; | |||
|
|
52 | ||||
|
|
53 | let Cookie = declare(null, { | |||
|
|
54 | secure: false, | |||
|
|
55 | httpOnly: false, | |||
|
|
56 | path: null, | |||
|
|
57 | name: null, | |||
|
|
58 | domain: null, | |||
|
|
59 | maxAge: null, | |||
|
|
60 | expires: null, | |||
|
|
61 | extension: null, | |||
|
|
62 | value: null, | |||
|
|
63 | format: "base64+json", | |||
|
|
64 | _createTime: null, | |||
|
|
65 | ||||
|
|
66 | constructor: function (name, value, opts) { | |||
|
|
67 | safe.argumentNotEmptyString(name, "name"); | |||
|
|
68 | ||||
|
|
69 | if (opts) { | |||
|
|
70 | for (let i in opts) | |||
|
|
71 | if (i in args) | |||
|
|
72 | this[i] = opts[i]; | |||
|
|
73 | } | |||
|
|
74 | ||||
|
|
75 | this.name = name; | |||
|
|
76 | this.value = value; | |||
|
|
77 | this._createTime = new Date(); | |||
|
|
78 | }, | |||
|
|
79 | ||||
|
|
80 | isExpired: function () { | |||
|
|
81 | let expires; | |||
|
|
82 | if (this.maxAge) { | |||
|
|
83 | let dt = this.getNormalMaxAge(); | |||
|
|
84 | expires = new Date(this._createTime.getTime() + dt * 1000); | |||
|
|
85 | } else if (this.expires) { | |||
|
|
86 | expires = new Date(this.expires); | |||
|
|
87 | } | |||
|
|
88 | ||||
|
|
89 | return (expires && new Date() > expires); | |||
|
|
90 | }, | |||
|
|
91 | ||||
|
|
92 | getNormalMaxAge: function () { | |||
|
|
93 | if (safe.isNull(this.maxAge)) | |||
|
|
94 | return null; | |||
|
|
95 | if (safe.isNumber(this.maxAge)) | |||
|
|
96 | return Math.round(this.maxAge); | |||
|
|
97 | ||||
|
|
98 | let norm = Number(this.maxAge); | |||
|
|
99 | ||||
|
|
100 | if (norm == this.maxAge) | |||
|
|
101 | return Math.round(norm); | |||
|
|
102 | ||||
|
|
103 | let parts = this.maxAge.toString().match("^(?:(\\d+)d)?(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$"); | |||
|
|
104 | if (parts) { | |||
|
|
105 | let factor = [0, 86400, 3600, 60, 1]; | |||
|
|
106 | norm = 0; | |||
|
|
107 | for (let i = 1; i < parts.length; i++) { | |||
|
|
108 | norm += factor[i] * (Number(parts[i]) || 0); | |||
|
|
109 | } | |||
|
|
110 | } else { | |||
|
|
111 | norm = null; | |||
|
|
112 | } | |||
|
|
113 | ||||
|
|
114 | return norm; | |||
|
|
115 | }, | |||
|
|
116 | ||||
|
|
117 | toString: function () { | |||
|
|
118 | let data = []; | |||
|
|
119 | ||||
|
|
120 | let pair = function (name, value, enc) { | |||
|
|
121 | if (!safe.isNullOrEmptyString(value)) | |||
|
|
122 | data.push([name, enc ? enc(value) : value].join('=')); | |||
|
|
123 | }; | |||
|
|
124 | ||||
|
|
125 | let flag = function (name, isSet) { | |||
|
|
126 | if (isSet) | |||
|
|
127 | data.push(name); | |||
|
|
128 | }; | |||
|
|
129 | ||||
|
|
130 | pair(this.name, this.value, this.format ? Cookie.formats[this.format].encode : null); | |||
|
|
131 | pair("Expires", this.expires, function (d) { | |||
|
|
132 | return new Date(d).toUTCString(); | |||
|
|
133 | }); | |||
|
|
134 | pair("Max-Age", this.getNormalMaxAge()); | |||
|
|
135 | pair("Domain", this.domain); | |||
|
|
136 | pair("Path", this.path); | |||
|
|
137 | flag("Secure", this.secure); | |||
|
|
138 | flag("HttpOnly", this.httpOnly); | |||
|
|
139 | flag(this.extension, this.extension); | |||
|
|
140 | ||||
|
|
141 | return data.join('; '); | |||
|
|
142 | } | |||
|
|
143 | ||||
|
|
144 | }); | |||
|
|
145 | ||||
|
|
146 | /** | |||
|
|
147 | * Парсит строку с печеньками из HTTP заголока Cookies | |||
|
|
148 | * | |||
|
|
149 | * @return возвращает коллекцию печенек в виде { "cookie-name" : { | |||
|
|
150 | * value='raw%20data', decode : function(format) {} } } | |||
|
|
151 | * | |||
|
|
152 | */ | |||
|
|
153 | Cookie.parseHeaderValue = function (str) { | |||
|
|
154 | safe.argumentNotEmptyString(str, "str"); | |||
|
|
155 | ||||
|
|
156 | let pairs = str.split(/;\s*/); | |||
|
|
157 | let cookies = {}; | |||
|
|
158 | ||||
|
|
159 | for (let i in pairs) { | |||
|
|
160 | let pair = pairs[i]; | |||
|
|
161 | let idx = pair.indexOf('='); | |||
|
|
162 | if (idx >= 0) { | |||
|
|
163 | cookies[pair.substring(0, idx)] = { | |||
|
|
164 | value: pair.substring(idx + 1), | |||
|
|
165 | decode: function (format) { | |||
|
|
166 | if (!format) | |||
|
|
167 | format = "simple"; | |||
|
|
168 | ||||
|
|
169 | if (!formats[format]) | |||
|
|
170 | throw new Error("The specified format '" + format + "' is unsupported"); | |||
|
|
171 | let decode = formats[format].decode; | |||
|
|
172 | ||||
|
|
173 | return decode(this.value); | |||
|
|
174 | } | |||
|
|
175 | }; | |||
|
|
176 | } | |||
|
|
177 | } | |||
|
|
178 | ||||
|
|
179 | return cookies; | |||
|
|
180 | ||||
|
|
181 | }; | |||
|
|
182 | ||||
|
|
183 | Cookie.formats = formats; | |||
|
|
184 | ||||
|
|
185 | Cookie.parse = function (str, format) { | |||
|
|
186 | safe.argumentNotEmptyString(str, "str"); | |||
|
|
187 | if (!format) | |||
|
|
188 | format = "simple"; | |||
|
|
189 | ||||
|
|
190 | if (!formats[format]) | |||
|
|
191 | throw new Error("The specified format '" + format + "' is unsupported"); | |||
|
|
192 | ||||
|
|
193 | let pairs = str.split(/;\s*/); | |||
|
|
194 | let options = { | |||
|
|
195 | format: format | |||
|
|
196 | }; | |||
|
|
197 | ||||
|
|
198 | let cookieName, cookieValue, first = true; | |||
|
|
199 | ||||
|
|
200 | let map = { | |||
|
|
201 | "Expires": "expires", | |||
|
|
202 | "Max-Age": "maxAge", | |||
|
|
203 | "Domain": "domain", | |||
|
|
204 | "Path": "path", | |||
|
|
205 | "Secure": "secure", | |||
|
|
206 | "HttpOnly": "httpOnly" | |||
|
|
207 | }; | |||
|
|
208 | ||||
|
|
209 | for (let i in pairs) { | |||
|
|
210 | let pair = pairs[i]; | |||
|
|
211 | let idx = pair.indexOf('='); | |||
|
|
212 | ||||
|
|
213 | if (idx >= 0) { | |||
|
|
214 | ||||
|
|
215 | let name = pair.substring(0, idx); | |||
|
|
216 | let value = pair.substring(idx + 1); | |||
|
|
217 | ||||
|
|
218 | if (first) { | |||
|
|
219 | cookieName = name; | |||
|
|
220 | cookieValue = value; | |||
|
|
221 | first = false; | |||
|
|
222 | } else { | |||
|
|
223 | if (name in map) | |||
|
|
224 | options[map[name]] = value; | |||
|
|
225 | } | |||
|
|
226 | } else { | |||
|
|
227 | if (pair in map) | |||
|
|
228 | options[map[pair]] = true; | |||
|
|
229 | else | |||
|
|
230 | options.extension = pair; | |||
|
|
231 | } | |||
|
|
232 | } | |||
|
|
233 | ||||
|
|
234 | return new Cookie(cookieName, cookieValue, options); | |||
|
|
235 | }; | |||
|
|
236 | ||||
|
|
237 | return Cookie; | |||
|
|
238 | }); No newline at end of file | |||
| @@ -0,0 +1,6 | |||||
|
|
1 | define(["dojo/_base/declare", "./HttpException"], function (declare, httpException) { | |||
|
|
2 | return declare([httpException], { | |||
|
|
3 | code: 403, | |||
|
|
4 | message: "Forbidden" | |||
|
|
5 | }); | |||
|
|
6 | }); | |||
| @@ -0,0 +1,9 | |||||
|
|
1 | define(["dojo/_base/declare","./HttpResponse"],function(declare,HttpResponse) { | |||
|
|
2 | return declare(null,{ | |||
|
|
3 | invoke: function(/*httpRequest, next*/) { | |||
|
|
4 | return new HttpResponse("Hello, world!",{ | |||
|
|
5 | contentType : "text/plain; charset=utf-8" | |||
|
|
6 | }); | |||
|
|
7 | } | |||
|
|
8 | }); | |||
|
|
9 | }); No newline at end of file | |||
| @@ -0,0 +1,11 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "./BaseApplication", | |||
|
|
4 | "dojo/node!http" | |||
|
|
5 | ], function(declare, base, http) { | |||
|
|
6 | return declare(base, { | |||
|
|
7 | _createServer : function(options, handler) { | |||
|
|
8 | return http.createServer(handler); | |||
|
|
9 | } | |||
|
|
10 | }); | |||
|
|
11 | }); No newline at end of file | |||
| @@ -0,0 +1,7 | |||||
|
|
1 | define(["dojo/_base/declare"], function (declare) { | |||
|
|
2 | return declare(null, { | |||
|
|
3 | code: 500, | |||
|
|
4 | message: "Internal server error", | |||
|
|
5 | headers: null | |||
|
|
6 | }); | |||
|
|
7 | }); | |||
| @@ -0,0 +1,123 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "dojo/Deferred", | |||
|
|
4 | "url", | |||
|
|
5 | "implab/safe", | |||
|
|
6 | "./Cookie", | |||
|
|
7 | "./ContentType", | |||
|
|
8 | "implab/log/trace!"], function (declare, Deferred, url, safe, Cookie, ContentType, trace) { | |||
|
|
9 | return declare([], { | |||
|
|
10 | ||||
|
|
11 | // http.IncommingMessage | |||
|
|
12 | message: null, | |||
|
|
13 | ||||
|
|
14 | response: null, | |||
|
|
15 | ||||
|
|
16 | session: null, | |||
|
|
17 | ||||
|
|
18 | cookieFormat: "base64+json", | |||
|
|
19 | _contentType: null, | |||
|
|
20 | _container: null, | |||
|
|
21 | _initialised: false, | |||
|
|
22 | ||||
|
|
23 | constructor: function (options) { | |||
|
|
24 | safe.argumentNotNull(options, "options"); | |||
|
|
25 | safe.argumentNotNull(options.container, "options.container"); | |||
|
|
26 | this._container = options.container; | |||
|
|
27 | ||||
|
|
28 | trace.log("Request created"); | |||
|
|
29 | }, | |||
|
|
30 | ||||
|
|
31 | init: function (message, response) { | |||
|
|
32 | safe.argumentNotNull(message, "message"); | |||
|
|
33 | ||||
|
|
34 | this.message = message; | |||
|
|
35 | this.method = message.method; | |||
|
|
36 | this.path = url.parse(message.url, true, true).pathname; | |||
|
|
37 | ||||
|
|
38 | this.response = response; | |||
|
|
39 | ||||
|
|
40 | this._initialised = true; | |||
|
|
41 | }, | |||
|
|
42 | ||||
|
|
43 | _checkInit: function () { | |||
|
|
44 | if(!this._initialised){ | |||
|
|
45 | throw new Error("Request is not initialised. 'init' function should be called"); | |||
|
|
46 | } | |||
|
|
47 | }, | |||
|
|
48 | ||||
|
|
49 | getService: function (service) { | |||
|
|
50 | return this._container.getService(service); | |||
|
|
51 | }, | |||
|
|
52 | ||||
|
|
53 | getContainer: function () { | |||
|
|
54 | return this._container; | |||
|
|
55 | }, | |||
|
|
56 | ||||
|
|
57 | getRemoteAddress: function () { | |||
|
|
58 | return this.message.socket.remoteAddress; | |||
|
|
59 | }, | |||
|
|
60 | ||||
|
|
61 | readAllText: function (encoding) { | |||
|
|
62 | this._checkInit(); | |||
|
|
63 | if (!encoding) | |||
|
|
64 | encoding = this.getContentType().parameters.charset || 'utf8'; | |||
|
|
65 | this.message.setEncoding(encoding); | |||
|
|
66 | ||||
|
|
67 | let d = new Deferred(); | |||
|
|
68 | ||||
|
|
69 | let chunks = []; | |||
|
|
70 | ||||
|
|
71 | this.message.on('data', function (chunk) { | |||
|
|
72 | chunks.push(chunk); | |||
|
|
73 | }); | |||
|
|
74 | this.message.on('end', function () { | |||
|
|
75 | d.resolve(chunks.join('')); | |||
|
|
76 | }); | |||
|
|
77 | this.message.on('error', function (e) { | |||
|
|
78 | d.reject(e); | |||
|
|
79 | }); | |||
|
|
80 | return d; | |||
|
|
81 | }, | |||
|
|
82 | ||||
|
|
83 | header: function (name) { | |||
|
|
84 | safe.argumentNotEmptyString(name, "name"); | |||
|
|
85 | this._checkInit(); | |||
|
|
86 | ||||
|
|
87 | return this.message.headers[name.toLowerCase()]; | |||
|
|
88 | }, | |||
|
|
89 | ||||
|
|
90 | getContentType: function () { | |||
|
|
91 | this._checkInit(); | |||
|
|
92 | if (safe.isNull(this._contentType)) | |||
|
|
93 | this._contentType = ContentType.parse(this.header('Content-Type')); | |||
|
|
94 | return this._contentType; | |||
|
|
95 | }, | |||
|
|
96 | /** Возвращает значение печеньки из запроса. | |||
|
|
97 | * @name Имя печеньки | |||
|
|
98 | * @format Формат значения, например json+base64 | |||
|
|
99 | * @return Объект со значением печеньки | |||
|
|
100 | */ | |||
|
|
101 | cookie: function (name, format) { | |||
|
|
102 | safe.argumentNotEmptyString(name, "name"); | |||
|
|
103 | this._checkInit(); | |||
|
|
104 | ||||
|
|
105 | if (!format) | |||
|
|
106 | format = this.cookieFormat; | |||
|
|
107 | ||||
|
|
108 | if (safe.isNull(this._cookies)) { | |||
|
|
109 | let cookiesHeader = this.header("Cookie"); | |||
|
|
110 | if (!safe.isNullOrEmptyString(cookiesHeader)) | |||
|
|
111 | this._cookies = Cookie.parseHeaderValue(cookiesHeader); | |||
|
|
112 | else | |||
|
|
113 | this._cookies = {}; | |||
|
|
114 | } | |||
|
|
115 | ||||
|
|
116 | let cookie = this._cookies[name]; | |||
|
|
117 | if (safe.isNull(cookie)) | |||
|
|
118 | return null; | |||
|
|
119 | ||||
|
|
120 | return cookie.decode(format); | |||
|
|
121 | } | |||
|
|
122 | }); | |||
|
|
123 | }); No newline at end of file | |||
| @@ -0,0 +1,137 | |||||
|
|
1 | define([ "dojo/_base/declare", "dojo/_base/lang", "implab/safe" ,"./ContentType", "./BaseResponse", "./Cookie" ], function(declare, lang,safe, ContentType, BaseResponse, Cookie) { | |||
|
|
2 | return declare(BaseResponse, { | |||
|
|
3 | statusCode : 0, | |||
|
|
4 | _headers : null, | |||
|
|
5 | content : null, | |||
|
|
6 | _contentType : null, | |||
|
|
7 | _cookies : null, | |||
|
|
8 | ||||
|
|
9 | getContentType : function() { | |||
|
|
10 | return this._contentType; | |||
|
|
11 | }, | |||
|
|
12 | ||||
|
|
13 | setContentType : function(value) { | |||
|
|
14 | if (value) { | |||
|
|
15 | this._contentType = value instanceof ContentType ? value : ContentType.parse(value.toString()); | |||
|
|
16 | this._headers["Content-Type"] = this._contentType.toString(); | |||
|
|
17 | } else { | |||
|
|
18 | this._contentType = null; | |||
|
|
19 | delete this._headers["Content-Type"]; | |||
|
|
20 | } | |||
|
|
21 | this._headers["Content-Type"] = value ? value.toString() : value; | |||
|
|
22 | }, | |||
|
|
23 | ||||
|
|
24 | /** | |||
|
|
25 | * Записывает cookies | |||
|
|
26 | * @cookie {String|Cookie} печенька или имя печеньки или печенька сохраненная в строку. | |||
|
|
27 | * @value? {*} если {cookie} строка с именем, то в этом параметре передается значение. | |||
|
|
28 | * @options? {Object} если {cookie} строка с именем, то в этом параметре передаются дополнительные свойства печенек. | |||
|
|
29 | */ | |||
|
|
30 | setCookie : function(cookie /*, value, options*/) { | |||
|
|
31 | if (arguments.length == 1) { | |||
|
|
32 | if (safe.isString(cookie)) | |||
|
|
33 | cookie = Cookie.parse(cookie); | |||
|
|
34 | safe.argumentOfType(cookie, Cookie, "cookie"); | |||
|
|
35 | this._cookies[cookie.name] = cookie; | |||
|
|
36 | } else { | |||
|
|
37 | safe.argumentNotEmptyString(cookie,"cookie"); | |||
|
|
38 | let value = arguments[1]; | |||
|
|
39 | let options = arguments[2]; | |||
|
|
40 | ||||
|
|
41 | let cc = new Cookie(cookie,value,options); | |||
|
|
42 | ||||
|
|
43 | this._cookies[cc.name] = cc; | |||
|
|
44 | } | |||
|
|
45 | }, | |||
|
|
46 | ||||
|
|
47 | _setCookies : function(cookies) { | |||
|
|
48 | if (!(cookies instanceof Array)) | |||
|
|
49 | cookies = [cookies]; | |||
|
|
50 | let me = this; | |||
|
|
51 | cookies.forEach(function(cookie){ | |||
|
|
52 | me.setCookie(cookie); | |||
|
|
53 | }); | |||
|
|
54 | }, | |||
|
|
55 | ||||
|
|
56 | forgetCookie : function(name) { | |||
|
|
57 | this.setCookie(new Cookie(name,"__erased__", { maxAge : 0 })); | |||
|
|
58 | }, | |||
|
|
59 | ||||
|
|
60 | setHeader : function(name, value) { | |||
|
|
61 | if (!name) | |||
|
|
62 | throw "A name is requried"; | |||
|
|
63 | name = this._normalizeHeaderName(name); | |||
|
|
64 | ||||
|
|
65 | if (name == "Content-Type") | |||
|
|
66 | this.setContentType(value); | |||
|
|
67 | if (name == "Set-Cookie") | |||
|
|
68 | this._setCookies(value); | |||
|
|
69 | else | |||
|
|
70 | this._headers[name] = value; | |||
|
|
71 | }, | |||
|
|
72 | ||||
|
|
73 | getHeader : function(name) { | |||
|
|
74 | if (!name) | |||
|
|
75 | throw "A name is requried"; | |||
|
|
76 | name = this._normalizeHeaderName(name); | |||
|
|
77 | ||||
|
|
78 | return this._headers[name]; | |||
|
|
79 | }, | |||
|
|
80 | ||||
|
|
81 | _normalizeHeaderName : function(name) { | |||
|
|
82 | return name.toLowerCase().replace(/\b\w/g, function(s) { | |||
|
|
83 | return s.toUpperCase(); | |||
|
|
84 | }); | |||
|
|
85 | }, | |||
|
|
86 | ||||
|
|
87 | constructor : function(content, options) { | |||
|
|
88 | this._headers = {}; | |||
|
|
89 | this._cookies = {}; | |||
|
|
90 | ||||
|
|
91 | this.content = content; | |||
|
|
92 | this.statusCode = content ? 200 : 203; | |||
|
|
93 | ||||
|
|
94 | if (options) { | |||
|
|
95 | if ("statusCode" in options) | |||
|
|
96 | this.statusCode = options.statusCode; | |||
|
|
97 | if ("headers" in options) { | |||
|
|
98 | for ( let header in options.headers) | |||
|
|
99 | this.setHeader(header, options.headers[header]); | |||
|
|
100 | } | |||
|
|
101 | if ("contentType" in options) | |||
|
|
102 | this.setContentType(options.contentType); | |||
|
|
103 | } | |||
|
|
104 | }, | |||
|
|
105 | ||||
|
|
106 | send : function(serverResponse) { | |||
|
|
107 | if (!serverResponse) | |||
|
|
108 | throw "ServerResponse is required"; | |||
|
|
109 | ||||
|
|
110 | this.writeHead(serverResponse); | |||
|
|
111 | ||||
|
|
112 | this.writeEntity(serverResponse); | |||
|
|
113 | ||||
|
|
114 | serverResponse.end(); | |||
|
|
115 | }, | |||
|
|
116 | ||||
|
|
117 | writeHead : function(serverResponse) { | |||
|
|
118 | let headers = lang.clone(this._headers); | |||
|
|
119 | let cookies = []; | |||
|
|
120 | for (let key in this._cookies) | |||
|
|
121 | cookies.push(this._cookies[key].toString()); | |||
|
|
122 | headers["Set-Cookie"] = cookies; | |||
|
|
123 | ||||
|
|
124 | serverResponse.writeHead(this.statusCode, headers); | |||
|
|
125 | }, | |||
|
|
126 | ||||
|
|
127 | writeEntity : function(serverResponse) { | |||
|
|
128 | if (this.content instanceof Function) { | |||
|
|
129 | this.content(serverResponse); | |||
|
|
130 | } else if (this.content) { | |||
|
|
131 | serverResponse.write(this.content, this._contentType ? this._contentType.parameters.charset : undefined); | |||
|
|
132 | } | |||
|
|
133 | } | |||
|
|
134 | ||||
|
|
135 | ||||
|
|
136 | }); | |||
|
|
137 | }); No newline at end of file | |||
| @@ -0,0 +1,93 | |||||
|
|
1 | define([], function() { | |||
|
|
2 | return { | |||
|
|
3 | application : { | |||
|
|
4 | atom: 'application/atom+xml', | |||
|
|
5 | json : 'application/json', | |||
|
|
6 | javascript: 'application/javascript', | |||
|
|
7 | octetStream: 'application/octet-stream', | |||
|
|
8 | ogg: 'application/ogg', | |||
|
|
9 | pdf: 'application/pdf', | |||
|
|
10 | soap: 'application/soap+xml', | |||
|
|
11 | xhtml: 'application/xhtml+xml', | |||
|
|
12 | dtd: 'application/xml-dtd', | |||
|
|
13 | zip: 'application/zip', | |||
|
|
14 | gzip: 'application/x-gzip', | |||
|
|
15 | form: 'application/x-www-form-urlencoded', | |||
|
|
16 | ttf: 'application/x-font-ttf', | |||
|
|
17 | tar: 'application/x-tar', | |||
|
|
18 | pkcs12: 'application/x-pkcs12', | |||
|
|
19 | pfx: 'application/x-pkcs12', | |||
|
|
20 | spc: 'application/x-pkcs7-certificates', | |||
|
|
21 | p7b: 'application/x-pkcs7-certificates', | |||
|
|
22 | p7r: 'application/x-pkcs7-certreqresp', | |||
|
|
23 | p7c: 'application/x-pkcs7-mime', | |||
|
|
24 | p7s: 'application/x-pkcs7-signature' | |||
|
|
25 | }, | |||
|
|
26 | audio : { | |||
|
|
27 | mulaw: 'audio/basic', | |||
|
|
28 | pcm24: 'audio/L24', | |||
|
|
29 | mp4: 'audio/mp4', | |||
|
|
30 | mp3: 'audio/mpeg', | |||
|
|
31 | mpeg: 'audio/mpeg', | |||
|
|
32 | ogg: 'audio/ogg', | |||
|
|
33 | vorbis: 'audio/vorbis', | |||
|
|
34 | wma: 'audio/x-ms-wma', | |||
|
|
35 | wmaRedirect: 'audio/x-ms-wax', | |||
|
|
36 | realAudio: 'audio/vnd.rn-realaudio', | |||
|
|
37 | wav: 'audio/vnd.wave', | |||
|
|
38 | webm: 'audio/webm' | |||
|
|
39 | }, | |||
|
|
40 | image: { | |||
|
|
41 | gif: 'image/gif', | |||
|
|
42 | jpeg: 'image/jpeg', | |||
|
|
43 | msJpeg: 'image/pjpeg', | |||
|
|
44 | png: 'image/png', | |||
|
|
45 | svg: 'image/svg+xml', | |||
|
|
46 | tiff: 'image/tiff', | |||
|
|
47 | ico: 'image/vnd.microsoft.icon', | |||
|
|
48 | wbmp: 'image/vnd.wap.wbmp', | |||
|
|
49 | bmp: 'image/bmp' | |||
|
|
50 | }, | |||
|
|
51 | message : { | |||
|
|
52 | http: 'message/http', | |||
|
|
53 | imdn: 'message/imdn+xml', | |||
|
|
54 | emailPartial: 'message/partial', | |||
|
|
55 | email: 'message/rfc822' | |||
|
|
56 | }, | |||
|
|
57 | model : { | |||
|
|
58 | example: 'model/example', | |||
|
|
59 | iges: 'model/iges', | |||
|
|
60 | mesh: 'model/mesh', | |||
|
|
61 | vrml: 'model/vrml', | |||
|
|
62 | x3db: 'model/x3d+binary', | |||
|
|
63 | x3dv: 'model/x3d+vrml', | |||
|
|
64 | x3d: 'model/x3d+xml' | |||
|
|
65 | }, | |||
|
|
66 | multipart: { | |||
|
|
67 | mixed: 'multipart/mixed', | |||
|
|
68 | alternative: 'multipart/alternative', | |||
|
|
69 | related: 'multipart/related', | |||
|
|
70 | form: 'multipart/form-data', | |||
|
|
71 | signed: 'multipart/signed', | |||
|
|
72 | encrypted: 'multipart/encrypted' | |||
|
|
73 | }, | |||
|
|
74 | text : { | |||
|
|
75 | cmd: 'text/cmd', | |||
|
|
76 | css: 'text/css', | |||
|
|
77 | csv: 'text/csv', | |||
|
|
78 | html: 'text/html', | |||
|
|
79 | plain: 'text/plain', | |||
|
|
80 | xml: 'text/xml' | |||
|
|
81 | }, | |||
|
|
82 | video: { | |||
|
|
83 | mpeg: 'video/mpeg', | |||
|
|
84 | mp4: 'video/mp4', | |||
|
|
85 | ogg: 'video/ogg', | |||
|
|
86 | quicktime: 'video/quicktime', | |||
|
|
87 | webm: 'video/webm', | |||
|
|
88 | wmv: 'video/x-ms-wmv', | |||
|
|
89 | flv: 'video/x-flv' | |||
|
|
90 | } | |||
|
|
91 | ||||
|
|
92 | }; | |||
|
|
93 | }); No newline at end of file | |||
| @@ -0,0 +1,29 | |||||
|
|
1 | define([ "dojo/_base/declare", "./HttpResponse" ], function(declare, HttpResponse) { | |||
|
|
2 | return declare(HttpResponse, { | |||
|
|
3 | presenter : null, | |||
|
|
4 | ||||
|
|
5 | constructor : function(model, options) { | |||
|
|
6 | if (options && options.presenter) | |||
|
|
7 | this.presenter = options.presenter; | |||
|
|
8 | }, | |||
|
|
9 | ||||
|
|
10 | send : function() { | |||
|
|
11 | console.log("try to present: " + this.content); | |||
|
|
12 | if (!this.presenter) | |||
|
|
13 | throw "The presenter isn't specified for the model '" + this.content + "'"; | |||
|
|
14 | ||||
|
|
15 | if (this.statusCode != 203 && this.presenter.contentType) | |||
|
|
16 | this.setHeader("Content-type", this.presenter.contentType); | |||
|
|
17 | ||||
|
|
18 | this.inherited(arguments); | |||
|
|
19 | ||||
|
|
20 | }, | |||
|
|
21 | ||||
|
|
22 | writeEntity : function(serverResponse) { | |||
|
|
23 | if (this.statusCode == 203) | |||
|
|
24 | return; | |||
|
|
25 | ||||
|
|
26 | serverResponse.write(this.presenter.present(this.content), this.getContentType() ? this.getContentType().parameters.charset : undefined); | |||
|
|
27 | } | |||
|
|
28 | }); | |||
|
|
29 | }); No newline at end of file | |||
| @@ -0,0 +1,6 | |||||
|
|
1 | define(["dojo/_base/declare", "./HttpException"], function (declare, httpException) { | |||
|
|
2 | return declare([httpException], { | |||
|
|
3 | code: 405, | |||
|
|
4 | message: "Method Not Allowed" | |||
|
|
5 | }); | |||
|
|
6 | }); | |||
| @@ -0,0 +1,6 | |||||
|
|
1 | define(["dojo/_base/declare", "./HttpException"], function (declare, httpException) { | |||
|
|
2 | return declare([httpException], { | |||
|
|
3 | code: 404, | |||
|
|
4 | message: "Not found" | |||
|
|
5 | }); | |||
|
|
6 | }); | |||
| @@ -0,0 +1,129 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "dojo/_base/lang", | |||
|
|
4 | "dojo/when", | |||
|
|
5 | "implab/safe", | |||
|
|
6 | "./NotAllowedException", | |||
|
|
7 | "./HttpResponse" | |||
|
|
8 | ], function ( | |||
|
|
9 | declare, | |||
|
|
10 | lang, | |||
|
|
11 | when, | |||
|
|
12 | safe, | |||
|
|
13 | NotAllowedException, | |||
|
|
14 | HttpResponse | |||
|
|
15 | ) { | |||
|
|
16 | let resource = declare(null, { | |||
|
|
17 | ||||
|
|
18 | // instance members | |||
|
|
19 | request: null, | |||
|
|
20 | ||||
|
|
21 | // родительский ресурс | |||
|
|
22 | parent: null, | |||
|
|
23 | ||||
|
|
24 | // имя текущего ресурса, является фрагментом пути к запрашиваемому | |||
|
|
25 | // ресурсу | |||
|
|
26 | name: null, | |||
|
|
27 | ||||
|
|
28 | allowedMethods: { | |||
|
|
29 | "head": 0, | |||
|
|
30 | "options": 0, | |||
|
|
31 | "get": 0, | |||
|
|
32 | "post": 0, | |||
|
|
33 | "put": 1, // extended method | |||
|
|
34 | "delete": 1 // extended method | |||
|
|
35 | }, | |||
|
|
36 | ||||
|
|
37 | constructor: function (options) { | |||
|
|
38 | if (options) { | |||
|
|
39 | declare.safeMixin(this, options); | |||
|
|
40 | } | |||
|
|
41 | }, | |||
|
|
42 | ||||
|
|
43 | accessCheck: null, | |||
|
|
44 | ||||
|
|
45 | getAllowedMethods: function (cors) { | |||
|
|
46 | let methods = []; | |||
|
|
47 | for (var m in this.allowedMethods) { | |||
|
|
48 | if (m in this && (cors && this.allowedMethods[m] || !cors)) | |||
|
|
49 | methods.push(m.toUpperCase()); | |||
|
|
50 | } | |||
|
|
51 | return methods; | |||
|
|
52 | }, | |||
|
|
53 | ||||
|
|
54 | options: function () { | |||
|
|
55 | let resp = new HttpResponse(null, { | |||
|
|
56 | headers: { | |||
|
|
57 | "Access-Control-Allow-Methods": this.getAllowedMethods(true), | |||
|
|
58 | "Allowed-Methods": this.getAllowedMethods() | |||
|
|
59 | } | |||
|
|
60 | }); | |||
|
|
61 | return resp; | |||
|
|
62 | }, | |||
|
|
63 | ||||
|
|
64 | invoke: function () { | |||
|
|
65 | let method = this.request.method.toLowerCase(); | |||
|
|
66 | ||||
|
|
67 | let me = this; | |||
|
|
68 | ||||
|
|
69 | if (!(method in this)) { | |||
|
|
70 | throw new NotAllowedException(); // TODO: Возвратить список возможных методов (verbs) | |||
|
|
71 | } | |||
|
|
72 | ||||
|
|
73 | if (!safe.isNull(this.accessCheck)) { | |||
|
|
74 | return when(this.request.session, function (session) { | |||
|
|
75 | me.session = session; | |||
|
|
76 | return when(me.accessCheck(), function () { | |||
|
|
77 | return me[method](); | |||
|
|
78 | }); | |||
|
|
79 | }, function (err) { | |||
|
|
80 | console.log(err); | |||
|
|
81 | throw err; | |||
|
|
82 | }); | |||
|
|
83 | } else { | |||
|
|
84 | return this[method](); | |||
|
|
85 | } | |||
|
|
86 | }, | |||
|
|
87 | ||||
|
|
88 | render: function (view, model, mimeType) { | |||
|
|
89 | return function (resp) { | |||
|
|
90 | if (mimeType) | |||
|
|
91 | resp.type(mimeType); | |||
|
|
92 | resp.render(view, { | |||
|
|
93 | model: model | |||
|
|
94 | }); | |||
|
|
95 | }; | |||
|
|
96 | ||||
|
|
97 | }, | |||
|
|
98 | ||||
|
|
99 | getChild: function (name) { | |||
|
|
100 | if (this.children && name in this.children) { | |||
|
|
101 | let child = this.children[name]; | |||
|
|
102 | ||||
|
|
103 | if (typeof child == "function") { | |||
|
|
104 | return child({ | |||
|
|
105 | request: this.request, | |||
|
|
106 | parent: this, | |||
|
|
107 | name: name | |||
|
|
108 | }); | |||
|
|
109 | } else if (child.hasOwnProperty("isInstanceOf") && child.isInstanceOf(resource)) { | |||
|
|
110 | return lang.mixin(child, { | |||
|
|
111 | request: this.request, | |||
|
|
112 | parent: this, | |||
|
|
113 | name: name | |||
|
|
114 | }); | |||
|
|
115 | } else { | |||
|
|
116 | return new resource(lang.mixin(child, { | |||
|
|
117 | request: this.request, | |||
|
|
118 | parent: this, | |||
|
|
119 | name: name | |||
|
|
120 | })); | |||
|
|
121 | } | |||
|
|
122 | } else { | |||
|
|
123 | return null; | |||
|
|
124 | } | |||
|
|
125 | } | |||
|
|
126 | }); | |||
|
|
127 | ||||
|
|
128 | return resource; | |||
|
|
129 | }); No newline at end of file | |||
| @@ -0,0 +1,50 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "dojo/_base/lang", | |||
|
|
4 | "dojo/when", | |||
|
|
5 | "./NotFoundException", | |||
|
|
6 | "./HttpException", | |||
|
|
7 | "./Resource", | |||
|
|
8 | "implab/safe" | |||
|
|
9 | ], | |||
|
|
10 | function (declare, lang, when, notFoundException, httpException, resource, safe) { | |||
|
|
11 | ||||
|
|
12 | return declare([], { | |||
|
|
13 | _resourcesConfig: null, | |||
|
|
14 | ||||
|
|
15 | constructor: function (options) { | |||
|
|
16 | safe.argumentNotNull(options, "options"); | |||
|
|
17 | safe.argumentNotNull(options.resourcesConfig, "options.resourcesConfig"); | |||
|
|
18 | ||||
|
|
19 | this._resourcesConfig = options.resourcesConfig; | |||
|
|
20 | }, | |||
|
|
21 | ||||
|
|
22 | createResource: function (req) { | |||
|
|
23 | let container = req.getContainer(); | |||
|
|
24 | return container.configure(this._resourcesConfig) | |||
|
|
25 | .then(function(){ | |||
|
|
26 | let rc = container.getService("resource"); | |||
|
|
27 | ||||
|
|
28 | if(rc.hasOwnProperty("isInstanceOf") && rc.isInstanceOf(resource)) { | |||
|
|
29 | return rc; | |||
|
|
30 | } else { | |||
|
|
31 | return new resource(lang.mixin(rc,{request: req})); | |||
|
|
32 | } | |||
|
|
33 | }); | |||
|
|
34 | }, | |||
|
|
35 | ||||
|
|
36 | invoke: function (req/*, next*/) { | |||
|
|
37 | return when(this.createResource(req), function (rc) { | |||
|
|
38 | req.path.split(/\/+/).forEach(function (child) { | |||
|
|
39 | if (child) { | |||
|
|
40 | rc = rc.getChild(child); | |||
|
|
41 | if (!rc) { | |||
|
|
42 | throw new notFoundException(); | |||
|
|
43 | } | |||
|
|
44 | } | |||
|
|
45 | }); | |||
|
|
46 | return rc.invoke(); | |||
|
|
47 | }); | |||
|
|
48 | } | |||
|
|
49 | }); | |||
|
|
50 | }); | |||
| @@ -0,0 +1,23 | |||||
|
|
1 | define([ "dojo/_base/declare", "./BaseResponse" ], function(declare, BaseResponse) { | |||
|
|
2 | /** | |||
|
|
3 | * Заглушка вместо ответа сервера, используется при использовании "родных" модулей | |||
|
|
4 | * node, требующи работы напрямую с ответом, для чего у HttpRequest запрашивается | |||
|
|
5 | * свйоство response, а вместо ответа возвращается заглушка. | |||
|
|
6 | */ | |||
|
|
7 | return declare(BaseResponse, { | |||
|
|
8 | _serverResponse : null, | |||
|
|
9 | ||||
|
|
10 | constructor : function(serverResponse) { | |||
|
|
11 | this._serverResponse = serverResponse; | |||
|
|
12 | }, | |||
|
|
13 | ||||
|
|
14 | setHeader : function() { | |||
|
|
15 | this._serverResponse.setHeader.apply(this._serverResponse, arguments); | |||
|
|
16 | }, | |||
|
|
17 | ||||
|
|
18 | send : function(serverResponse) { | |||
|
|
19 | if (!serverResponse.finished) | |||
|
|
20 | serverResponse.end(); | |||
|
|
21 | } | |||
|
|
22 | }); | |||
|
|
23 | }); No newline at end of file | |||
| @@ -0,0 +1,18 | |||||
|
|
1 | /** | |||
|
|
2 | * Created by internet on 6/21/16. | |||
|
|
3 | */ | |||
|
|
4 | 'user strict'; | |||
|
|
5 | /*===== | |||
|
|
6 | return { | |||
|
|
7 | // summary: | |||
|
|
8 | // The implab package main module; implab package is somewhat unusual in that the main module currently just provides an empty object. | |||
|
|
9 | // Apps should require modules from the implab packages directly, rather than loading this module. | |||
|
|
10 | }; | |||
|
|
11 | =====*/ | |||
|
|
12 | ||||
|
|
13 | /** | |||
|
|
14 | The entry point | |||
|
|
15 | @module implab | |||
|
|
16 | */ | |||
|
|
17 | ||||
|
|
18 | module.exports = {}; No newline at end of file | |||
| @@ -0,0 +1,13 | |||||
|
|
1 | /** | |||
|
|
2 | * Created by andrei on 22.08.16. | |||
|
|
3 | */ | |||
|
|
4 | define(['dojo/_base/declare'], function(declare){ | |||
|
|
5 | let AuthCode = declare(null, { | |||
|
|
6 | }); | |||
|
|
7 | ||||
|
|
8 | AuthCode.SUCCSESS = 0; | |||
|
|
9 | AuthCode.INCMPLETE = 1; | |||
|
|
10 | AuthCode.FAIL = 2; | |||
|
|
11 | ||||
|
|
12 | return AuthCode; | |||
|
|
13 | }); | |||
| @@ -0,0 +1,93 | |||||
|
|
1 | /** | |||
|
|
2 | * Модуль, отвечающий за создание контекста безопасности (сессии). | |||
|
|
3 | * | |||
|
|
4 | * Идентификатор сессии сохраняется в печеньках на клиенте. | |||
|
|
5 | */ | |||
|
|
6 | define([ | |||
|
|
7 | "dojo/_base/declare", | |||
|
|
8 | "dojo/when", | |||
|
|
9 | "implab/safe", | |||
|
|
10 | "../Cookie", | |||
|
|
11 | "../security/SecData", | |||
|
|
12 | "../BaseResponse", | |||
|
|
13 | "implab/log/trace!" | |||
|
|
14 | ], function (declare, when, safe, Cookie, SecData, BaseResponse, trace) { | |||
|
|
15 | let COOKIE_NAME = "ssid"; | |||
|
|
16 | ||||
|
|
17 | return declare(null, { | |||
|
|
18 | _request : null, | |||
|
|
19 | _provider : null, | |||
|
|
20 | _cookies : null, | |||
|
|
21 | _sessionData: null, | |||
|
|
22 | ||||
|
|
23 | constructor : function(options) { | |||
|
|
24 | safe.argumentNotNull(options, "options"); | |||
|
|
25 | safe.argumentNotNull(options.securityProvider, "options.securityProvider"); | |||
|
|
26 | safe.argumentNotNull(options.request, "options.request"); | |||
|
|
27 | ||||
|
|
28 | this._request = options.request; | |||
|
|
29 | this._provider = options.securityProvider; | |||
|
|
30 | this._cookies = []; | |||
|
|
31 | }, | |||
|
|
32 | ||||
|
|
33 | /** | |||
|
|
34 | * Вызывается из {SecurityHandler} по окончании обработки запроса. | |||
|
|
35 | * | |||
|
|
36 | * @resp ответ сервера | |||
|
|
37 | */ | |||
|
|
38 | completeRequest : function(resp) { | |||
|
|
39 | trace.log("completeRequest"); | |||
|
|
40 | if (resp instanceof BaseResponse) | |||
|
|
41 | this._cookies.forEach(function(cookie) { | |||
|
|
42 | resp.setCookie(cookie); | |||
|
|
43 | }); | |||
|
|
44 | if (!safe.isNull(this._sessionData)) | |||
|
|
45 | return this._sessionData.save().then(function () { | |||
|
|
46 | return resp; | |||
|
|
47 | }); | |||
|
|
48 | return resp; | |||
|
|
49 | }, | |||
|
|
50 | ||||
|
|
51 | handleError : function(err) { | |||
|
|
52 | throw err; | |||
|
|
53 | }, | |||
|
|
54 | ||||
|
|
55 | initSession : function(userIdentity) { | |||
|
|
56 | safe.argumentNotNull(userIdentity, "userIdentity"); | |||
|
|
57 | let me = this; | |||
|
|
58 | ||||
|
|
59 | return when(me._provider.getSessions().createSession(userIdentity, SecData.newSSID()), function(session) { | |||
|
|
60 | if (!session) { | |||
|
|
61 | throw new Error("Can`t init session"); | |||
|
|
62 | } | |||
|
|
63 | ||||
|
|
64 | me._sessionData = session; | |||
|
|
65 | trace.log("Created session {0} for user {1}", session.sessionId, userIdentity.getUser().login); | |||
|
|
66 | me._cookies.push(new Cookie(COOKIE_NAME,session.sessionId)); | |||
|
|
67 | return session; | |||
|
|
68 | }); | |||
|
|
69 | }, | |||
|
|
70 | ||||
|
|
71 | /* aync */ | |||
|
|
72 | getSession : function() { | |||
|
|
73 | let cookie; | |||
|
|
74 | let me = this; | |||
|
|
75 | try { | |||
|
|
76 | cookie = this._request.cookie(COOKIE_NAME); | |||
|
|
77 | ||||
|
|
78 | if (!cookie) | |||
|
|
79 | return null; | |||
|
|
80 | ||||
|
|
81 | return when(me._provider.getSessions().getSession(cookie), function(session) { | |||
|
|
82 | me._sessionData = session; | |||
|
|
83 | return session; | |||
|
|
84 | }); | |||
|
|
85 | } catch (e) { | |||
|
|
86 | trace.log("getSession: {0}", e); | |||
|
|
87 | return null; | |||
|
|
88 | } | |||
|
|
89 | } | |||
|
|
90 | ||||
|
|
91 | }); | |||
|
|
92 | ||||
|
|
93 | }); No newline at end of file | |||
| @@ -0,0 +1,81 | |||||
|
|
1 | /** | |||
|
|
2 | * @class Identity идентификационная информация (удостоверение) пользователя. | |||
|
|
3 | * Описывает пользователя и способ его аутентификации в системе. Данный | |||
|
|
4 | * класс является заглушкой, описывающей интерфейс, а также может | |||
|
|
5 | * использоваться для создания идентификацинной информации вручную. | |||
|
|
6 | */ | |||
|
|
7 | define([ | |||
|
|
8 | "dojo/_base/declare", | |||
|
|
9 | "implab/safe", | |||
|
|
10 | "./SecData" | |||
|
|
11 | ], function (declare, safe, SecData) { | |||
|
|
12 | let identity = declare(null, { | |||
|
|
13 | _user : null, | |||
|
|
14 | ||||
|
|
15 | _isAnonymous : null, | |||
|
|
16 | ||||
|
|
17 | _secData : null, | |||
|
|
18 | ||||
|
|
19 | constructor : function(user, opts) { | |||
|
|
20 | this._user = user; | |||
|
|
21 | safe.mixin(this, opts, { | |||
|
|
22 | isAnonymous : '_isAnonymous', | |||
|
|
23 | secData : '_secData' | |||
|
|
24 | }); | |||
|
|
25 | }, | |||
|
|
26 | ||||
|
|
27 | getUser : function() { | |||
|
|
28 | return this._user; | |||
|
|
29 | }, | |||
|
|
30 | ||||
|
|
31 | getSecData : function() { | |||
|
|
32 | return this._secData; | |||
|
|
33 | }, | |||
|
|
34 | ||||
|
|
35 | /** | |||
|
|
36 | * Проводит раунд аутентификации, изменяет текущее состояние. Делегирует | |||
|
|
37 | * выполнение процедуры объекту SecData. | |||
|
|
38 | * | |||
|
|
39 | * @param challenge | |||
|
|
40 | * {*} - данные для аутентификации, зависит от реализации, | |||
|
|
41 | * например, пароль. | |||
|
|
42 | * @retuns authResult {Object} - результат аутентификации { challenge : | |||
|
|
43 | * 'response data', code : AUTH_* }. | |||
|
|
44 | * @throws {Error} | |||
|
|
45 | * в случае ошибки или если модуль аутентификации не задан. | |||
|
|
46 | */ | |||
|
|
47 | doAuth : function(challenge) { | |||
|
|
48 | if (this._secData) | |||
|
|
49 | return this._secData.doAuth(challenge); | |||
|
|
50 | ||||
|
|
51 | throw new Error("Authentication is not available for this object"); | |||
|
|
52 | }, | |||
|
|
53 | ||||
|
|
54 | getAuthType : function() { | |||
|
|
55 | if (this._secData) | |||
|
|
56 | return this._secData.getAuthType(); | |||
|
|
57 | ||||
|
|
58 | return null; | |||
|
|
59 | }, | |||
|
|
60 | ||||
|
|
61 | getIsAuthenticated : function() { | |||
|
|
62 | if (this._secData) { | |||
|
|
63 | return this._secData.getAuthSate() == SecData.AUTH_SUCCESS; | |||
|
|
64 | } | |||
|
|
65 | return false; | |||
|
|
66 | }, | |||
|
|
67 | ||||
|
|
68 | getIsAnonymous : function() { | |||
|
|
69 | return this._isAnonymous; | |||
|
|
70 | }, | |||
|
|
71 | ||||
|
|
72 | getAuthState : function() { | |||
|
|
73 | if (this._secData) | |||
|
|
74 | return this._secData.getAuthState(); | |||
|
|
75 | ||||
|
|
76 | throw new Error("Authentication is not available for this object"); | |||
|
|
77 | } | |||
|
|
78 | }); | |||
|
|
79 | ||||
|
|
80 | return identity; | |||
|
|
81 | }); No newline at end of file | |||
| @@ -0,0 +1,18 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", | |||
|
|
3 | "./SecData" | |||
|
|
4 | ], function (declare, SecData) { | |||
|
|
5 | return declare(SecData, { | |||
|
|
6 | doAuth: function (/*challenge*/) { | |||
|
|
7 | return { | |||
|
|
8 | code: SecData.AUTH_SUCCESS | |||
|
|
9 | }; | |||
|
|
10 | }, | |||
|
|
11 | getAuthState: function () { | |||
|
|
12 | return SecData.AUTH_SUCCESS; | |||
|
|
13 | }, | |||
|
|
14 | getAuthType: function () { | |||
|
|
15 | return "none"; | |||
|
|
16 | } | |||
|
|
17 | }); | |||
|
|
18 | }); No newline at end of file | |||
| @@ -0,0 +1,73 | |||||
|
|
1 | define([ | |||
|
|
2 | "dojo/_base/declare", "dojo/node!crypto"], function (declare, crypto) { | |||
|
|
3 | let SecData = declare(null, { | |||
|
|
4 | _state: null, | |||
|
|
5 | _token: null, | |||
|
|
6 | _authType: null, | |||
|
|
7 | ||||
|
|
8 | constructor: function (authType) { | |||
|
|
9 | this._authType = authType; | |||
|
|
10 | }, | |||
|
|
11 | ||||
|
|
12 | /** | |||
|
|
13 | * Проводит раунд аутентификации, изменяет текущее состояние. | |||
|
|
14 | * @param challenge {*} - данные для аутентификации, зависит от реализации, например, пароль. | |||
|
|
15 | * @retuns authResult {Object} - результат аутентификации { challenge : 'response data', code : AUTH_* }. | |||
|
|
16 | */ | |||
|
|
17 | doAuth: function (challenge) { | |||
|
|
18 | let password = challenge; | |||
|
|
19 | ||||
|
|
20 | if (this.validateHash(password)) { | |||
|
|
21 | this._state = SecData.AUTH_SUCCESS; | |||
|
|
22 | } else { | |||
|
|
23 | this._state = SecData.AUTH_FAIL; | |||
|
|
24 | } | |||
|
|
25 | ||||
|
|
26 | return { | |||
|
|
27 | code: this._state | |||
|
|
28 | }; | |||
|
|
29 | ||||
|
|
30 | }, | |||
|
|
31 | getAuthState: function () { | |||
|
|
32 | return this._state; | |||
|
|
33 | }, | |||
|
|
34 | getAuthType: function () { | |||
|
|
35 | return this._authType; | |||
|
|
36 | }, | |||
|
|
37 | ||||
|
|
38 | generateHash: function (password) { | |||
|
|
39 | return md5hex(password); | |||
|
|
40 | }, | |||
|
|
41 | parse: function (token) { | |||
|
|
42 | this._token = token; | |||
|
|
43 | }, | |||
|
|
44 | ||||
|
|
45 | validateHash: function (password) { | |||
|
|
46 | return this.generateHash(password) == this._token; | |||
|
|
47 | } | |||
|
|
48 | }); | |||
|
|
49 | ||||
|
|
50 | ||||
|
|
51 | SecData.AUTH_SUCCESS = 0; | |||
|
|
52 | SecData.AUTH_INCOMPLETE = 1; | |||
|
|
53 | SecData.AUTH_FAIL = 2; | |||
|
|
54 | ||||
|
|
55 | ||||
|
|
56 | function md5hex() { | |||
|
|
57 | let md5 = crypto.createHash('md5'); | |||
|
|
58 | ||||
|
|
59 | for (let i = 0; i < arguments.length; i++) | |||
|
|
60 | md5.update(String(arguments[i])); | |||
|
|
61 | ||||
|
|
62 | return md5.digest('hex'); | |||
|
|
63 | } | |||
|
|
64 | ||||
|
|
65 | let i = 0; | |||
|
|
66 | ||||
|
|
67 | SecData.md5hex = md5hex; | |||
|
|
68 | SecData.newSSID = function () { | |||
|
|
69 | return md5hex(new Date().getTime(), Math.random(), i++); | |||
|
|
70 | }; | |||
|
|
71 | ||||
|
|
72 | return SecData; | |||
|
|
73 | }); No newline at end of file | |||
| @@ -0,0 +1,56 | |||||
|
|
1 | /** | |||
|
|
2 | * Обработчик системы безопасности, встраивается в стек обработки запросов и | |||
|
|
3 | * контролирует процесс создания контекста безопасности регистрирует в запросе | |||
|
|
4 | * сервис с именем session. | |||
|
|
5 | * | |||
|
|
6 | * Для получения и создания контекста безопасности используется | |||
|
|
7 | * SecurityAuthority которое отвечает за механизмы проверки подлинности и | |||
|
|
8 | * доверенность полученной сессии, по сути SecurityAuthority реализует протокол | |||
|
|
9 | * безопасности. | |||
|
|
10 | * | |||
|
|
11 | * При первом доступе к сервисам возможна прозрачная аутентификация, при этом | |||
|
|
12 | * создается новая сессия, для ее создания используется IdentityProvider. | |||
|
|
13 | * IdentityProvider - внешний модуль аутентификации, который по требованию | |||
|
|
14 | * предоставляет идентификатор пользователя, используя собственные механизмы. | |||
|
|
15 | * | |||
|
|
16 | * После получения данных аутентификации от IdentityProvider они используются в | |||
|
|
17 | * SecurityAuthority для создания сессии. | |||
|
|
18 | * | |||
|
|
19 | * Многоэтапная аутентификация сессии - случай пока чисто теоретический, оданко, | |||
|
|
20 | * в случае необходимости SecurityAuthtority вызывает исключение при получении | |||
|
|
21 | * сесии, если требуется следующий этап аутентификации сессии, данное исключение | |||
|
|
22 | * прерывает текущую обработку запроса и попадает в обработчик | |||
|
|
23 | * SecurityAuthority.handleError который в свою очередь формирует ответ сервера | |||
|
|
24 | * для продолжения аутентификации. | |||
|
|
25 | */ | |||
|
|
26 | define([ "dojo/_base/declare", "dojo/when"], | |||
|
|
27 | function(declare, when) { | |||
|
|
28 | ||||
|
|
29 | return declare(null, { | |||
|
|
30 | constructor : function(/*options*/) { | |||
|
|
31 | }, | |||
|
|
32 | ||||
|
|
33 | /** | |||
|
|
34 | * Точка входа в обработчик, вызывается инфраструктурой при | |||
|
|
35 | * обработке запроса. | |||
|
|
36 | * | |||
|
|
37 | * @req Текущий запрос. | |||
|
|
38 | * @next Следующий обработчик в цепочке, вызывается когда сессия уже | |||
|
|
39 | * зарегистрирована в локаторе. | |||
|
|
40 | * @async | |||
|
|
41 | */ | |||
|
|
42 | invoke : function(req, next) { | |||
|
|
43 | let authority = req.getService("securityAuthority"); | |||
|
|
44 | return when(next(), function(resp) { | |||
|
|
45 | if (authority) | |||
|
|
46 | return authority.completeRequest(resp); | |||
|
|
47 | return resp; | |||
|
|
48 | }, function(err) { | |||
|
|
49 | if (authority) | |||
|
|
50 | return authority.handleError(err); | |||
|
|
51 | else | |||
|
|
52 | throw err; | |||
|
|
53 | }); | |||
|
|
54 | } | |||
|
|
55 | }); | |||
|
|
56 | }); | |||
| @@ -0,0 +1,31 | |||||
|
|
1 | /** | |||
|
|
2 | * Created by andrei on 21.08.16. | |||
|
|
3 | */ | |||
|
|
4 | define([ | |||
|
|
5 | "dojo/_base/declare", | |||
|
|
6 | "implab/safe", | |||
|
|
7 | "./NoneSecData", | |||
|
|
8 | "./SecData" | |||
|
|
9 | ], function(declare, safe, NoneSecData, SecData) { | |||
|
|
10 | let SecurityServices = declare(null, { | |||
|
|
11 | }); | |||
|
|
12 | ||||
|
|
13 | SecurityServices.getSecurityDataService = function(tokenType) { | |||
|
|
14 | switch (tokenType) { | |||
|
|
15 | case this.PASSWORD_AUTH_TYPE: | |||
|
|
16 | return new SecData(tokenType); | |||
|
|
17 | case this.SATISFY_ANY_AUTH_TYPE: | |||
|
|
18 | return new NoneSecData(); | |||
|
|
19 | case this.REJECT_ALL_AUTH_TYPE: | |||
|
|
20 | throw Error("NotImplemented"); | |||
|
|
21 | default: | |||
|
|
22 | throw Error("Unsupported auth type " + tokenType); | |||
|
|
23 | } | |||
|
|
24 | ||||
|
|
25 | }; | |||
|
|
26 | SecurityServices.PASSWORD_AUTH_TYPE = "password"; | |||
|
|
27 | SecurityServices.SATISFY_ANY_AUTH_TYPE = "satisfyany"; | |||
|
|
28 | SecurityServices.REJECT_ALL_AUTH_TYPE = "rejectall"; | |||
|
|
29 | ||||
|
|
30 | return SecurityServices; | |||
|
|
31 | }); | |||
| @@ -0,0 +1,101 | |||||
|
|
1 | /** | |||
|
|
2 | * Created by andrei on 08.04.16. | |||
|
|
3 | */ | |||
|
|
4 | define([ | |||
|
|
5 | "dojo/_base/declare", | |||
|
|
6 | "dojo/_base/lang", | |||
|
|
7 | "dojo/when", | |||
|
|
8 | "implab/safe", | |||
|
|
9 | "../ForbiddenException"], | |||
|
|
10 | function (declare, lang, when, safe, ForbiddenException) { | |||
|
|
11 | return declare(null, { | |||
|
|
12 | _container: null, | |||
|
|
13 | _sessionData: null, | |||
|
|
14 | /** | |||
|
|
15 | * Создавать анонимную сессию. Если прозрачная аутентификация не | |||
|
|
16 | * проводилась, и текущей сессии нет, то может быть создана сессия | |||
|
|
17 | * для анонимного пользователя. Это сделано опцией, поскольку не во | |||
|
|
18 | * всех системах требуется, отслеживать активность анонимных | |||
|
|
19 | * пользователей (это не бесплатно). | |||
|
|
20 | */ | |||
|
|
21 | _createAnonymousSession: false, | |||
|
|
22 | ||||
|
|
23 | /** | |||
|
|
24 | * Регистрировать пользователей, полученных из внешнего источника | |||
|
|
25 | * аутентификации. | |||
|
|
26 | */ | |||
|
|
27 | _autoRegisterUsers: false, | |||
|
|
28 | ||||
|
|
29 | constructor: function (options) { | |||
|
|
30 | safe.argumentNotNull(options, "options"); | |||
|
|
31 | safe.argumentNotNull(options.container, "options.container"); | |||
|
|
32 | ||||
|
|
33 | this._container = options.container; | |||
|
|
34 | ||||
|
|
35 | this._createAnonymousSession = options.createAnonymousSession || this._createAnonymousSession; | |||
|
|
36 | this._autoRegisterUsers = options.autoRegisterUsers || this._autoRegisterUsers; | |||
|
|
37 | ||||
|
|
38 | this._sessionData = this._initSession(); | |||
|
|
39 | }, | |||
|
|
40 | getSessionData: function () { | |||
|
|
41 | return this._sessionData; | |||
|
|
42 | }, | |||
|
|
43 | ||||
|
|
44 | /** | |||
|
|
45 | * @remarks Сосздание/восстановление сессии происходит в несколько | |||
|
|
46 | * этапов 1. Получаем текущую сессию. 2. Если упешно, то | |||
|
|
47 | * выходим. 3. Получаем идентификатор пользователя, | |||
|
|
48 | * используя identityProvider 4. Если успешно 5. Создаем | |||
|
|
49 | * новую сессию для полученного пользователя, выходим 6. | |||
|
|
50 | * Иначе если установлен параметр _createAnonymousSession 7. | |||
|
|
51 | * Создаем новую анонимную сессию. 8. Иначе, выходим | |||
|
|
52 | */ | |||
|
|
53 | _initSession: function () { | |||
|
|
54 | let me = this; | |||
|
|
55 | ||||
|
|
56 | let securityAuthority = me._container.getService("securityAuthority"); | |||
|
|
57 | let securityProvider = me._container.getService("securityProvider"); | |||
|
|
58 | let identityProvider = me._container.getService("identityProvider"); | |||
|
|
59 | ||||
|
|
60 | if (!securityAuthority) | |||
|
|
61 | throw new Error("Sessions are not supported, no security authority is supplied"); | |||
|
|
62 | ||||
|
|
63 | ||||
|
|
64 | // пытаемся получить текущую сессию | |||
|
|
65 | return when(securityAuthority.getSession(), function (session) { | |||
|
|
66 | if (session) | |||
|
|
67 | return session; | |||
|
|
68 | ||||
|
|
69 | // пытаемся создать сессию с использованием | |||
|
|
70 | // пользователя из внешнего | |||
|
|
71 | // источника аутентификации | |||
|
|
72 | if (identityProvider) { | |||
|
|
73 | return when(identityProvider.getUserLogin(), function (login) { | |||
|
|
74 | if (login) { | |||
|
|
75 | return when(securityProvider.createUserIdentity(login, false, { | |||
|
|
76 | createUser: me._autoRegisterUsers | |||
|
|
77 | }), function (uid) { | |||
|
|
78 | return securityAuthority.initSession(uid); | |||
|
|
79 | }, function (err) { | |||
|
|
80 | console.log("Failed to create session for '" + login + "' ", err); | |||
|
|
81 | throw new ForbiddenException(); | |||
|
|
82 | }); | |||
|
|
83 | } else if (me._createAnonymousSession) { | |||
|
|
84 | return when(securityProvider.getAnonymousIdentity(), function (uid) { | |||
|
|
85 | return securityAuthority.initSession(uid); | |||
|
|
86 | }); | |||
|
|
87 | } else { | |||
|
|
88 | throw new ForbiddenException(); | |||
|
|
89 | } | |||
|
|
90 | }); | |||
|
|
91 | } else if (me._createAnonymousSession) { | |||
|
|
92 | return when(securityProvider.getAnonymousIdentity(), function (uid) { | |||
|
|
93 | return securityAuthority.initSession(uid); | |||
|
|
94 | }); | |||
|
|
95 | } | |||
|
|
96 | ||||
|
|
97 | throw new ForbiddenException(); | |||
|
|
98 | }); | |||
|
|
99 | } | |||
|
|
100 | }); | |||
|
|
101 | }); No newline at end of file | |||
| @@ -0,0 +1,40 | |||||
|
|
1 | { | |||
|
|
2 | "extends": "tslint:recommended", | |||
|
|
3 | "rules": { | |||
|
|
4 | "align": [ | |||
|
|
5 | true, | |||
|
|
6 | "parameters", | |||
|
|
7 | "statements" | |||
|
|
8 | ], | |||
|
|
9 | "interface-name": [false], | |||
|
|
10 | "max-line-length": [ true, 185 ], | |||
|
|
11 | "member-access": false, | |||
|
|
12 | "member-ordering": [ | |||
|
|
13 | false, | |||
|
|
14 | "variables-before-functions" | |||
|
|
15 | ], | |||
|
|
16 | "no-bitwise": false, | |||
|
|
17 | "no-empty": false, | |||
|
|
18 | "no-namespace": false, | |||
|
|
19 | "no-string-literal": false, | |||
|
|
20 | "ordered-imports": false, | |||
|
|
21 | "one-line": [ | |||
|
|
22 | true, | |||
|
|
23 | "check-open-brace", | |||
|
|
24 | "check-catch", | |||
|
|
25 | "check-whitespace" | |||
|
|
26 | ], | |||
|
|
27 | "object-literal-sort-keys": false, | |||
|
|
28 | "trailing-comma": [ | |||
|
|
29 | true, | |||
|
|
30 | { | |||
|
|
31 | "singleline": "never", | |||
|
|
32 | "multiline": "never" | |||
|
|
33 | } | |||
|
|
34 | ], | |||
|
|
35 | "variable-name": false, | |||
|
|
36 | "curly": false, | |||
|
|
37 | "array-type": false, | |||
|
|
38 | "arrow-parens": [true, "ban-single-arg-parens"] | |||
|
|
39 | } | |||
|
|
40 | } No newline at end of file | |||
General Comments 0
You need to be logged in to leave comments.
Login now
