├── project ├── build.properties ├── plugins.sbt ├── Tests.scala └── sed.scala ├── blue-web └── src │ └── main │ ├── resources │ ├── webapp │ │ ├── ace │ │ │ ├── mode-text.js │ │ │ ├── snippets │ │ │ │ ├── text.js │ │ │ │ └── latex.js │ │ │ ├── ext-error_marker.js │ │ │ ├── ext-linking.js │ │ │ ├── ext-statusbar.js │ │ │ ├── ext-spellcheck.js │ │ │ ├── ext-themelist.js │ │ │ ├── theme-xcode.js │ │ │ ├── theme-kuroir.js │ │ │ ├── theme-clouds.js │ │ │ ├── theme-eclipse.js │ │ │ ├── theme-github.js │ │ │ ├── theme-vibrant_ink.js │ │ │ ├── theme-dawn.js │ │ │ ├── theme-merbivore.js │ │ │ ├── theme-idle_fingers.js │ │ │ ├── theme-kr_theme.js │ │ │ ├── theme-solarized_dark.js │ │ │ ├── theme-cobalt.js │ │ │ ├── theme-solarized_light.js │ │ │ └── theme-monokai.js │ │ ├── partials │ │ │ ├── paper_load.html │ │ │ ├── logout.html │ │ │ ├── paper │ │ │ │ ├── error.html │ │ │ │ ├── load.html │ │ │ │ └── latex │ │ │ │ │ └── reviewer.html │ │ │ ├── paper.html │ │ │ ├── 404.html │ │ │ ├── paper_share_menu.html │ │ │ ├── reset.html │ │ │ ├── messages.html │ │ │ ├── login.html │ │ │ ├── menu.html │ │ │ └── resetPassword.html │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── img │ │ │ ├── logo.png │ │ │ ├── logo.psd │ │ │ ├── spin.gif │ │ │ ├── favicon.png │ │ │ ├── favicon.psd │ │ │ ├── login-logo.png │ │ │ ├── login-logo.psd │ │ │ └── login-logo - copie.psd │ │ ├── css │ │ │ └── fonts │ │ │ │ ├── bluelatexicon.eot │ │ │ │ ├── bluelatexicon.ttf │ │ │ │ └── bluelatexicon.woff │ │ ├── lib │ │ │ ├── GravatarDirective.js │ │ │ ├── angular-autoFillSync.js │ │ │ ├── ngStorage.min.js │ │ │ └── angular │ │ │ │ └── angular-loader.min.js │ │ ├── js │ │ │ ├── shared │ │ │ │ ├── directives │ │ │ │ │ ├── MenuDirective.js │ │ │ │ │ ├── MessagesDirective.js │ │ │ │ │ ├── AutoFocusDirective.js │ │ │ │ │ └── LocalizeTooltipDirective.js │ │ │ │ └── controllers │ │ │ │ │ └── MessagesController.js │ │ │ └── user │ │ │ │ ├── controllers │ │ │ │ └── LogoutUserController.js │ │ │ │ └── services │ │ │ │ └── SessionService.js │ │ └── LICENSE │ └── application.conf │ ├── scala │ └── gnieh │ │ └── blue │ │ └── web │ │ ├── AppConfig.scala │ │ ├── WebApp.scala │ │ ├── BlueWebActivator.scala │ │ └── ConfigLet.scala │ └── assets │ └── less │ └── css.less ├── blue-test └── src │ ├── it │ └── resources │ │ └── resource.txt │ └── main │ ├── resources │ └── logback.xml │ └── scala │ └── gnieh │ └── blue │ ├── UserRole.scala │ ├── CompilerSettings.scala │ ├── Person.scala │ └── Paper.scala ├── blue-mobwrite └── src │ └── main │ ├── resources │ └── reference.conf │ └── scala │ └── gnieh │ └── blue │ └── mobwrite │ ├── MobwriteActivator.scala │ └── MobwriteServer.scala ├── bnd ├── jsch.bnd ├── activation.bnd ├── blue-sync.bnd ├── blue-core.bnd ├── blue-web.bnd ├── blue-mobwrite.bnd ├── blue-compile.bnd └── blue-common.bnd ├── src └── main │ ├── configuration │ ├── texmf.cnf │ ├── logback.xml │ └── org.gnieh.blue.common │ │ └── application.conf │ ├── templates │ ├── gitignore │ ├── emails │ │ ├── register-info.mustache │ │ ├── reset.mustache │ │ └── register-confirm.mustache │ ├── generic.tex.mustache │ ├── beamer.tex.mustache │ ├── llncs.tex.mustache │ ├── index.html.mustache │ ├── sigproc-sp.tex.mustache │ └── sig-alternate.tex.mustache │ └── designs │ ├── blue_users │ └── lists.json │ └── blue_papers │ ├── lists.json │ └── papers.json ├── blue-dist └── src │ ├── configuration │ ├── texmf.cnf │ ├── logback.xml │ └── org.gnieh.blue.common │ │ └── application.conf │ ├── jsvc │ ├── blue-stop.sh │ └── blue-start.sh │ ├── systemd │ └── bluelatex.service │ └── shell │ ├── install.sh │ └── upgrade.sh ├── blue-common └── src │ └── main │ ├── resources │ └── reference.conf │ └── scala │ └── gnieh │ └── blue │ ├── couch │ ├── impl │ │ ├── BlueSerializers.scala │ │ └── DbManager.scala │ ├── Paper.scala │ ├── UserPermissions.scala │ ├── PaperPhase.scala │ ├── User.scala │ └── PaperRole.scala │ ├── common │ ├── ReCaptcha.scala │ ├── MailAgent.scala │ ├── SetUtils.scala │ ├── impl │ │ ├── TemplatesImpl.scala │ │ ├── LogServiceFactory.scala │ │ └── ReCaptchaImpl.scala │ ├── Templates.scala │ ├── Hook.scala │ ├── ConfigurationLoader.scala │ ├── Logging.scala │ ├── PaperConfiguration.scala │ ├── SynchroServer.scala │ ├── BlueConfiguration.scala │ └── package.scala │ ├── permission │ ├── Group.scala │ ├── Permission.scala │ ├── Phase.scala │ ├── Role.scala │ └── package.scala │ └── http │ ├── ErrorResponse.scala │ ├── SessionKeys.scala │ └── impl │ ├── RestServiceTracker.scala │ └── BlueServer.scala ├── CONTRIBUTORS ├── .travis.yml ├── .gitignore ├── blue-sync └── src │ └── main │ └── scala │ └── gnieh │ └── blue │ └── sync │ └── impl │ ├── package.scala │ ├── Document.scala │ ├── SyncApi.scala │ ├── store │ └── Store.scala │ ├── EditCommandParser.scala │ └── SyncDispatcher.scala ├── blue-compile └── src │ └── main │ ├── scala │ └── gnieh │ │ └── blue │ │ └── compile │ │ ├── CompilerSettings.scala │ │ └── impl │ │ ├── package.scala │ │ ├── CompilationStatus.scala │ │ ├── let │ │ ├── GetCompilersLet.scala │ │ └── CleanLet.scala │ │ ├── compiler │ │ ├── XelatexCompiler.scala │ │ ├── LualatexCompiler.scala │ │ ├── PdflatexCompiler.scala │ │ └── LatexCompiler.scala │ │ └── SettingsHooks.scala │ └── resources │ └── application.conf ├── blue-core └── src │ └── main │ └── scala │ └── gnieh │ └── blue │ └── core │ └── impl │ ├── session │ ├── GetSessionDataLet.scala │ ├── LogoutLet.scala │ └── LoginLet.scala │ ├── user │ ├── GetUserInfoLet.scala │ ├── GetUsersLet.scala │ ├── SaveUserPermissionsLet.scala │ ├── GetUserPapersLet.scala │ └── GetUserPermissionsLet.scala │ ├── paper │ ├── JoinPaperLet.scala │ ├── SynchronizedResourcesLet.scala │ ├── DeleteResourceLet.scala │ ├── PartPaperLet.scala │ ├── GetPaperPermissionsLet.scala │ └── NonSynchronizedResourcesLet.scala │ └── BlueCoreActivator.scala └── changelog └── v1.0.x.markdown /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.11 2 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/mode-text.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper_load.html: -------------------------------------------------------------------------------- 1 | Loading... 2 | -------------------------------------------------------------------------------- /blue-test/src/it/resources/resource.txt: -------------------------------------------------------------------------------- 1 | This is an example text file to upload 2 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /blue-test/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /blue-mobwrite/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | mobwrite { 2 | 3 | url = "localhost" 4 | 5 | port = 3017 6 | 7 | } 8 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/favicon.ico -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/favicon.png -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/logo.png -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/logo.psd -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/spin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/spin.gif -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/favicon.png -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/favicon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/favicon.psd -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/login-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/login-logo.png -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/login-logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/login-logo.psd -------------------------------------------------------------------------------- /bnd/jsch.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Name: com.jcraft.jsch 2 | Bundle-SymbolicName: com.jcraft.jsch 3 | Export-Package: * 4 | 5 | Import-Package: *;resolution:=optional 6 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/logout.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Goodbye

4 |
-------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper/error.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Error

4 |
-------------------------------------------------------------------------------- /bnd/activation.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Name: activation 2 | Bundle-SymbolicName: activation 3 | Export-Package: * 4 | Frangment-Host: javax.mail 5 | 6 | Import-Package: * 7 | 8 | -------------------------------------------------------------------------------- /src/main/configuration/texmf.cnf: -------------------------------------------------------------------------------- 1 | % disallow opening any file starting with a `.' and any file in 2 | % a path going up into the parent directory. 3 | openin_any = p 4 | -------------------------------------------------------------------------------- /blue-dist/src/configuration/texmf.cnf: -------------------------------------------------------------------------------- 1 | % disallow opening any file starting with a `.' and any file in 2 | % a path going up into the parent directory. 3 | openin_any = p 4 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/img/login-logo - copie.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/img/login-logo - copie.psd -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.eot -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.ttf -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnieh/bluelatex/HEAD/blue-web/src/main/resources/webapp/css/fonts/bluelatexicon.woff -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper/load.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Loading...

4 |
5 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/snippets/text.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/snippets/text",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="text"}) -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /blue-common/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | # Make akka less verbose about dead letters 2 | akka { 3 | 4 | log-dead-letters = false 5 | 6 | log-dead-letters-during-shutdown = false 7 | 8 | } 9 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/404.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

404

4 |

This is ot the web page you are looking for.

5 |
-------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/ext-error_marker.js: -------------------------------------------------------------------------------- 1 | ; 2 | (function() { 3 | ace.require(["ace/ext/error_marker"], function() {}); 4 | })(); 5 | -------------------------------------------------------------------------------- /bnd/blue-sync.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.sync.impl.SyncServerActivator 2 | Bundle-SymbolicName: org.gnieh.blue.sync 3 | Bundle-Name: \\BlueLaTeX Native Synchronization server 4 | 5 | Import-Package=* 6 | 7 | Private-Package=gnieh.blue.sync 8 | 9 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Contributors of \BlueLaTeX 2 | 3 | Copyright 2013 Lucas Satabin 4 | Copyright 2013 Audric Schiltknecht 5 | Copyright 2014 Lucas Satabin 6 | Copyright 2014 Audric Schiltknecht 7 | Copyright 2014 Thomas Durieux 8 | Copyright 2014 Martin Monperrus 9 | -------------------------------------------------------------------------------- /bnd/blue-core.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.core.impl.BlueCoreActivator 2 | Bundle-SymbolicName: org.gnieh.blue.core 3 | Bundle-Name: \\BlueLaTeX Server Core Features (user management, paper management, ...) 4 | 5 | Private-Package=gnieh.blue.core.impl 6 | Import-Package=* 7 | 8 | -------------------------------------------------------------------------------- /src/main/templates/gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.glo 3 | *.idx 4 | *.log 5 | *.toc 6 | *.ist 7 | *.acn 8 | *.acr 9 | *.alg 10 | *.bbl 11 | *.blg 12 | *.dvi 13 | *.glg 14 | *.gls 15 | *.ilg 16 | *.ind 17 | *.lof 18 | *.lot 19 | *.maf 20 | *.mtc 21 | *.mtc1 22 | *.out 23 | *.synctex.gz -------------------------------------------------------------------------------- /bnd/blue-web.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.web.BlueWebActivator 2 | Bundle-SymbolicName: org.gnieh.blue.web 3 | Bundle-Name: \\BlueLaTeX Web client 4 | Provide-Capability: org.gnieh.blue.sync 5 | Private-Package=gnieh.blue.web 6 | Import-Package=gnieh.blue.common,gnieh.blue.compile,* 7 | -------------------------------------------------------------------------------- /bnd/blue-mobwrite.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.mobwrite.MobwriteActivator 2 | Bundle-SymbolicName: org.gnieh.blue.mobwrite 3 | Bundle-Name: \\BlueLaTeX Binding to Mobwrite Synchronization Server 4 | Provide-Capability: org.gnieh.blue.sync 5 | 6 | Private-Package=gnieh.blue.mobwrite 7 | 8 | -------------------------------------------------------------------------------- /bnd/blue-compile.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.compile.impl.CompilationActivator 2 | Bundle-SymbolicName: org.gnieh.blue.compile 3 | Bundle-Name: \\BlueLaTeX Compilation Feature 4 | 5 | Private-Package=gnieh.blue.compile.impl 6 | 7 | Import-Package=* 8 | 9 | Export-Package=gnieh.blue.compile 10 | 11 | -------------------------------------------------------------------------------- /src/main/templates/emails/register-info.mustache: -------------------------------------------------------------------------------- 1 | Hi {{firstName}}, 2 | 3 | Thank your for registering with the \BlueLaTeX service at {{baseUrl}}. 4 | 5 | Your login is: {{name}} 6 | Your registration email address is: {{email}} 7 | 8 | Thank you for using \BlueLaTeX 9 | 10 | Your \BlueLaTeX team 11 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | blue { 2 | 3 | client { 4 | 5 | # prefix where the web application is located 6 | path-prefix = "" 7 | 8 | issues-url = "https://github.com/gnieh/bluelatex/issues/new" 9 | 10 | clone-url = "https://github.com/gnieh/bluelatex/" 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper_share_menu.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /src/main/designs/blue_users/lists.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "_design/lists", 3 | "language": "javascript", 4 | "views": { 5 | "emails": { 6 | "map": "function(doc) { if(doc.email && doc.name) { emit(doc.name, doc.email); } }" 7 | } 8 | "names": { 9 | "map": "function(doc) { if(doc.name) { emit(doc.name, null); } }" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /blue-dist/src/jsvc/blue-stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /usr/bin/jsvc \ 4 | -wait 10 \ 5 | -java-home /usr/lib/jvm/default-java \ 6 | -cp $install_dir/bin/blue-launcher.jar \ 7 | -user $blue_user \ 8 | -pidfile /var/run/bluelatex.pid \ 9 | -outfile $log_dir/bluelatex.out \ 10 | -errfile $log_dir/bluelatex.err \ 11 | -stop \ 12 | org.gnieh.blue.launcher.Main 13 | -------------------------------------------------------------------------------- /blue-dist/src/systemd/bluelatex.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=\\BlueLaTeX Server 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/usr/bin/java -Dfelix.config.properties=file:$conf_dir/config.properties -cp $install_dir/bin/blue-launcher.jar org.apache.felix.main.Main 7 | Restart=on-failure 8 | User=$blue_user 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /src/main/configuration/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ./blue-server.log 4 | true 5 | 6 | %level [%d] %logger: %msg%n%ex 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /blue-dist/src/configuration/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $log_dir/bluelatex.log 4 | true 5 | 6 | %level [%d] %logger: %msg%n%ex 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /blue-dist/src/configuration/org.gnieh.blue.common/application.conf: -------------------------------------------------------------------------------- 1 | http { 2 | 3 | port = 8080 4 | 5 | host = "127.0.0.1" 6 | 7 | } 8 | 9 | blue { 10 | 11 | data = $data_dir 12 | 13 | } 14 | 15 | couch { 16 | 17 | admin-name = "admin" 18 | 19 | admin-password = "admin" 20 | 21 | } 22 | 23 | mail { 24 | 25 | smtp { 26 | 27 | host = "127.0.0.1" 28 | 29 | port = 25 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /blue-dist/src/jsvc/blue-start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /usr/bin/jsvc \ 4 | -wait 10 \ 5 | -java-home /usr/lib/jvm/default-java \ 6 | -cp $install_dir/bin/blue-launcher.jar \ 7 | -user $blue_user \ 8 | -pidfile /var/run/bluelatex.pid \ 9 | -outfile $log_dir/bluelatex.out \ 10 | -errfile $log_dir/bluelatex.err \ 11 | -Dfelix.config.properties="file:$conf_dir/config.properties" \ 12 | org.gnieh.blue.launcher.Main 13 | -------------------------------------------------------------------------------- /src/main/configuration/org.gnieh.blue.common/application.conf: -------------------------------------------------------------------------------- 1 | http { 2 | 3 | port = 18080 4 | 5 | } 6 | 7 | blue { 8 | 9 | data = "./data" 10 | 11 | } 12 | 13 | couch { 14 | 15 | port = $couchPort 16 | 17 | admin-name = $couchAdmin 18 | 19 | admin-password = $couchPassword 20 | 21 | } 22 | 23 | mail { 24 | 25 | smtp { 26 | 27 | host = "127.0.0.1" 28 | 29 | port = 12525 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/templates/emails/reset.mustache: -------------------------------------------------------------------------------- 1 | Hi, 2 | 3 | We received a password reset request for your account {{name}}. 4 | 5 | To actually change your password, please follow this link: 6 | {{baseUrl}}/index.html#/{{name}}/reset/{{token}} 7 | 8 | This link is valid during {{validity}} days. 9 | 10 | If you did not request a password reset, you can just ignore this email. 11 | 12 | Thank you for using \BlueLaTeX 13 | 14 | Your \BlueLaTeX team 15 | -------------------------------------------------------------------------------- /bnd/blue-common.bnd: -------------------------------------------------------------------------------- 1 | Bundle-Activator: gnieh.blue.common.impl.BlueCommonActivator 2 | Bundle-SymbolicName: org.gnieh.blue.common 3 | Bundle-Name: Common bundle allowing other bundles to load configuration, log event and use utilities 4 | 5 | Private-Package=gnieh.blue.common.impl, gnieh.blue.couch.impl, gnieh.blue.http.impl 6 | Import-Package=* 7 | 8 | Export-Package=gnieh.blue.common, gnieh.blue.couch, gnieh.blue.http, gnieh.blue.permission 9 | 10 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/lib/GravatarDirective.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * A directive bl-gravatar witch display the gravatar of email 4 | */ 5 | angular.module('bluelatex.Gravatar', ['angular-md5','gdi2290.gravatar-filter']) 6 | .directive('blGravatar', [function () { 7 | return { 8 | scope: { 9 | email: '=email' 10 | }, 11 | template: '' 12 | }; 13 | }]); -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | 3 | scala: 4 | - 2.10.6 5 | 6 | # only trigger builds on master 7 | branches: 8 | only: 9 | - master 10 | - v1.0.x 11 | 12 | script: 13 | - "sbt test blue-test/scenario:test" 14 | 15 | services: 16 | - couchdb 17 | 18 | before_install: 19 | - sudo apt-get update -qq 20 | - sudo apt-get install -qq jsvc 21 | 22 | before_script: 23 | - "echo \"couchdb := None\n\ncouchPort := 5984\n\" > build.sbt" 24 | 25 | after_script: 26 | - "cat /tmp/bluelatex.err" 27 | -------------------------------------------------------------------------------- /src/main/templates/emails/register-confirm.mustache: -------------------------------------------------------------------------------- 1 | Hi {{firstName}}, 2 | 3 | You just registered to the \BlueLaTeX service. 4 | 5 | Your login is: {{name}} 6 | Your registration email address is: {{email}} 7 | 8 | To activate your account and set your password, please follow this link: 9 | {{baseUrl}}/index.html#/{{name}}/reset/{{token}} 10 | 11 | This link is valid during {{validity}} days. 12 | 13 | If you did not register to the \Blue service, you can just ignore this email. 14 | 15 | Thank you for using \BlueLaTeX 16 | 17 | Your \BlueLaTeX team 18 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | scalacOptions += "-deprecation" 2 | 3 | resolvers += "Sonatype Snapshots" at "http://oss.sonatype.org/content/repositories/snapshots/" 4 | 5 | resolvers += Resolver.typesafeRepo("releases") 6 | 7 | libraryDependencies += "biz.aQute.bnd" % "bndlib" % "2.2.0" 8 | 9 | libraryDependencies += "org.gnieh" %% "sohva-testing" % "0.4" 10 | 11 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.2.5") 12 | 13 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2") 14 | 15 | addSbtPlugin("com.typesafe.sbt" % "sbt-web" % "1.1.0") 16 | 17 | addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.0.0") 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # use glob syntax. 2 | syntax: glob 3 | *.ser 4 | *.class 5 | *~ 6 | *.bak 7 | #*.off 8 | *.old 9 | *.pyc 10 | *.swp 11 | 12 | # eclipse conf file 13 | .cache 14 | .settings 15 | .classpath 16 | .project 17 | .manager 18 | .scala_dependencies 19 | 20 | # idea 21 | .idea 22 | *.iml 23 | 24 | # building 25 | target 26 | build 27 | null 28 | tmp* 29 | #temp* 30 | dist 31 | test-output 32 | build.log 33 | build.sbt 34 | 35 | # other scm 36 | .svn 37 | .CVS 38 | .hg* 39 | 40 | # switch to regexp syntax. 41 | # syntax: regexp 42 | # ^\.pc/ 43 | 44 | #SHITTY output not in target directory 45 | build.log 46 | 47 | # macos files 48 | .DS_Store 49 | .Trashes 50 | 51 | -------------------------------------------------------------------------------- /src/main/templates/generic.tex.mustache: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | \documentclass{<% class %>} 3 | 4 | \usepackage[T1]{fontenc} %% to get Type 1 fonts 5 | \usepackage[utf8]{inputenc} %% to enable non ASCII characters 6 | \usepackage[margin=2cm]{geometry} %% to change the margins 7 | 8 | \title{<% title %>} 9 | 10 | \author{ 11 | <% author %>\\ 12 | <% email %>\\ 13 | <% affiliation %> 14 | \and 15 | Your Co-Author\\ 16 | second@email.com\\ 17 | Institute 18 | } 19 | 20 | \begin{document} 21 | \maketitle 22 | 23 | \section{First Section} 24 | Some text 25 | 26 | \section{Second Section} 27 | 28 | % to add the bibliography, uncomment the following lines 29 | %\bibliography{references}{} 30 | %\bibliographystyle{plain} 31 | \end{document} 32 | -------------------------------------------------------------------------------- /src/main/designs/blue_papers/lists.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "_design/lists", 3 | "language": "javascript", 4 | "views": { 5 | "by_author": { 6 | "map": "function(doc) {\n if(doc.authors) {\n for(var i = 0; i < doc.authors.length ; i++) {\n emit(doc.authors[i], {\"_id\": doc._id, \"title\": doc.title});\n }\n }\n}" 7 | }, 8 | "title": { 9 | "map": "function(doc) {\n if(doc.title) {\n emit(doc._id, doc.title);\n }\n}" 10 | }, 11 | "by_keyword": { 12 | "map": "function(doc) {\n if(doc.keywords) {\n for(var i = 0; i < doc.keywords.length ; i++) {\n emit(doc.keywords[i], {\"_id\": doc._id, \"title\": doc.title});\n }\n }\n}" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/lib/angular-autoFillSync.js: -------------------------------------------------------------------------------- 1 | /** 2 | * autoFillSync 3 | * autoFillSync directive for AngularJS 4 | * By Ben Lesh 5 | * From http://stackoverflow.com/questions/14965968/angularjs-browser-autofill-workaround-by-using-a-directive 6 | */ 7 | 8 | angular.module('autoFillSync', [] ) 9 | .directive('autoFillSync', function($timeout) { 10 | return { 11 | require: 'ngModel', 12 | link: function(scope, elem, attrs, ngModel) { 13 | var origVal = elem.val(); 14 | $timeout(function () { 15 | var newVal = elem.val(); 16 | if(ngModel.$pristine && origVal !== newVal) { 17 | ngModel.$setViewValue(newVal); 18 | } 19 | }, 500); 20 | } 21 | } 22 | }); -------------------------------------------------------------------------------- /blue-test/src/main/scala/gnieh/blue/UserRole.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | 18 | case class UserRole(id: String, name: String, role: String) 19 | -------------------------------------------------------------------------------- /blue-test/src/main/scala/gnieh/blue/CompilerSettings.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | 18 | case class CompilerSettings(compiler: String, timeout: Int, interval: Int) 19 | 20 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/impl/BlueSerializers.scala: -------------------------------------------------------------------------------- 1 | package gnieh.blue 2 | package couch 3 | package impl 4 | 5 | import net.liftweb.json._ 6 | 7 | import gnieh.sohva.SohvaSerializer 8 | 9 | import permission._ 10 | 11 | object PermissionSerializer extends Serializer[Permission] { 12 | 13 | val PermissionClass = classOf[Permission] 14 | 15 | def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Permission] = { 16 | case (TypeInfo(PermissionClass, _), JString(name)) => 17 | Permission(name) 18 | } 19 | 20 | def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { 21 | case Permission(name) => JString(name) 22 | } 23 | 24 | } 25 | 26 | object BluePermissionSerializer extends SohvaSerializer[Permission] { 27 | def serializer(v: String) = 28 | PermissionSerializer 29 | } 30 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/ext-linking.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"],function(e,t,n){function i(e){var t=e.editor,n=e.getAccelKey();if(n){var t=e.editor,r=e.getDocumentPosition(),i=t.session,s=i.getTokenAt(r.row,r.column);t._emit("linkHover",{position:r,token:s})}}function s(e){var t=e.getAccelKey(),n=e.getButton();if(n==0&&t){var r=e.editor,i=e.getDocumentPosition(),s=r.session,o=s.getTokenAt(i.row,i.column);r._emit("linkClick",{position:i,token:o})}}var r=e("ace/editor").Editor;e("../config").defineOptions(r.prototype,"editor",{enableLinking:{set:function(e){e?(this.on("click",s),this.on("mousemove",i)):(this.off("click",s),this.off("mousemove",i))},value:!1}})}); 2 | (function() { 3 | ace.require(["ace/ext/linking"], function() {}); 4 | })(); 5 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/ReCaptcha.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | import tiscaf.HTalk 20 | 21 | trait ReCaptcha { 22 | 23 | def verify(talk: HTalk): Boolean 24 | 25 | } 26 | -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | 19 | package object impl { 20 | type PeerId = String 21 | type PaperId = String 22 | type Filepath = String 23 | } 24 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/MailAgent.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | trait MailAgent { 20 | 21 | /** Sends an email to the given user */ 22 | def send(username: String, subject: String, text: String): Unit 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/templates/beamer.tex.mustache: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | \documentclass{beamer} 3 | 4 | \usepackage[T1]{fontenc} %% to get Type 1 fonts 5 | \usepackage[utf8]{inputenc} %% to enable non ASCII characters 6 | 7 | \title{<% title %>} 8 | 9 | \institute{% 10 | \inst{1}% 11 | <% email %>\\ 12 | <% affiliation %> 13 | } 14 | 15 | \author{<% author %>\inst{1}} 16 | 17 | \subject{\LaTeX} 18 | 19 | \AtBeginSection[]{ 20 | \begin{frame} 21 | \frametitle{Table of Contents} 22 | \tableofcontents[currentsection] 23 | \end{frame} 24 | } 25 | 26 | \begin{document} 27 | 28 | \frame{\titlepage} 29 | 30 | \begin{frame} 31 | \frametitle{This is the first slide} 32 | %Content goes here 33 | \end{frame} 34 | 35 | \begin{frame} 36 | \frametitle{This is the second slide} 37 | \framesubtitle{A bit more information about this} 38 | %More content goes here 39 | \end{frame} 40 | 41 | % etc 42 | \end{document} 43 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/CompilerSettings.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | 19 | import gnieh.sohva.IdRev 20 | 21 | case class CompilerSettings(_id: String, compiler: String, synctex: Boolean, timeout: Int, interval: Int) extends IdRev 22 | 23 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/Paper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue.couch 17 | 18 | import gnieh.sohva.IdRev 19 | 20 | import java.util.Date 21 | 22 | case class Paper(_id: String, 23 | name: String, 24 | creation_date: Date) extends IdRev 25 | 26 | -------------------------------------------------------------------------------- /src/main/templates/llncs.tex.mustache: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | % template for Lecture Notes in Computer Science 3 | % for more explanations look at http://www.springer.com/computer/lncs?SGWID=0-164-6-793341-0 4 | 5 | \documentclass{llncs} 6 | 7 | \begin{document} 8 | 9 | \title{<% title %>} 10 | 11 | \author{<% author %>\inst{1} \and Your Co-Author\inst{2}} 12 | 13 | \institute{<%email %>, <% affiliation %>, Street, City, Country 14 | \and 15 | Institute, Street, City, Country} 16 | 17 | \maketitle 18 | % 19 | \begin{abstract} 20 | This is the abstract. 21 | \end{abstract} 22 | % 23 | \section{Introduction} 24 | Your wonderful introduction 25 | 26 | \section{Remainder of Your Paper} 27 | 28 | blablabla 29 | 30 | % 31 | % The following two commands are all you need in the 32 | % initial runs of your .tex file to 33 | % produce the bibliography for the citations in your paper. 34 | %\bibliography{references} 35 | 36 | \end{document} 37 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/shared/directives/MenuDirective.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * A directive used to display the menu 19 | */ 20 | angular.module('bluelatex.Shared.Directives.Menu', []) 21 | .directive('blMenu', function() { 22 | return { 23 | templateUrl: 'partials/menu.html' 24 | }; 25 | }); -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/shared/directives/MessagesDirective.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * A directive used to display messages 19 | */ 20 | angular.module('bluelatex.Shared.Directives.Messages', []) 21 | .directive('blMessages', function() { 22 | return { 23 | templateUrl: 'partials/messages.html' 24 | }; 25 | }); -------------------------------------------------------------------------------- /blue-web/src/main/scala/gnieh/blue/web/AppConfig.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package web 18 | 19 | case class AppConfig(api_prefix: String, 20 | require_validation: Boolean, 21 | recaptcha_public_key: Option[String], 22 | compilation_type: Option[String], 23 | issues_url: Option[String], 24 | clone_url: Option[String]) 25 | -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/Document.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | package impl 19 | 20 | import java.io.File 21 | 22 | /** Server-side document 23 | * 24 | * @author Lucas Satabin 25 | */ 26 | class Document(val path: String, var text: String) { 27 | lazy val filename = new File(path).getName() 28 | } 29 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/permission/Group.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package permission 18 | 19 | import gnieh.sohva.IdRev 20 | 21 | /** A group of users may be created to factorize some permissions. 22 | * 23 | * @author Lucas Satabin 24 | */ 25 | case class Group(_id: String, name: String, users: List[String]) extends IdRev 26 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/shared/directives/AutoFocusDirective.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | // A directive witch give the focus on an element 19 | angular.module('bluelatex.Shared.Directives.Autofocus', []) 20 | .directive('autofocus', function() { 21 | return function(scope, elem, attr) { 22 | elem[0].focus(); 23 | }; 24 | }); -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/http/ErrorResponse.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package http 18 | 19 | /** An error response with an error name and a description. 20 | * All API should return an error response when something went wrong. 21 | * 22 | * @author Lucas Satabin 23 | */ 24 | case class ErrorResponse(name: String, description: String) 25 | 26 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/SetUtils.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | object SingletonSet { 20 | def unapply[T](set: Set[T]): Option[T] = 21 | if(set.size == 1) 22 | set.headOption 23 | else 24 | None 25 | } 26 | 27 | object EmptySet { 28 | def unapply[T](set: Set[T]): Boolean = 29 | set.isEmpty 30 | } 31 | -------------------------------------------------------------------------------- /src/main/templates/index.html.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | publications.li - {{title}} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/permission/Permission.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package permission 18 | 19 | /** A permission on paper that defines how certain user may interact on the paper 20 | * 21 | * @author Lucas Satabin 22 | */ 23 | final case class Permission(val name: String) { 24 | def unapply(permissions: Set[Permission]): Boolean = 25 | permissions.contains(this) 26 | } 27 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | 19 | import common._ 20 | 21 | import java.io.File 22 | 23 | package object impl { 24 | implicit class CompileConfiguration(val config: PaperConfiguration) extends AnyVal { 25 | 26 | def buildDir(paperId: String) = 27 | new File(config.paperDir(paperId), "build") 28 | 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/UserPermissions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue.couch 17 | 18 | import gnieh.sohva._ 19 | 20 | /** Users may define their own set of permissions and save them so 21 | * that he can reuse them later on. 22 | * 23 | * @author Lucas Satabin 24 | * 25 | */ 26 | case class UserPermissions(_id: String, 27 | permissions: Map[String, Map[String, Set[String]]]) extends IdRev 28 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/permission/Phase.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package permission 18 | 19 | import gnieh.sohva.IdRev 20 | 21 | /** A `Phase` defines the different permission for each role that are allowed. 22 | * By putting a paper into a specific phase, one can restrict allowed operations. 23 | * 24 | * @author Lucas Satabin 25 | */ 26 | case class Phase(_id: String, name: String, permissions: Map[Role, Set[Permission]]) extends IdRev 27 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/ext-statusbar.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"],function(e,t,n){"use strict";var r=e("ace/lib/dom"),i=e("ace/lib/lang"),s=function(e,t){this.element=r.createElement("div"),this.element.className="ace_status-indicator",this.element.style.cssText="display: inline-block;",t.appendChild(this.element);var n=i.delayedCall(function(){this.updateStatus(e)}.bind(this)).schedule.bind(null,100);e.on("changeStatus",n),e.on("changeSelection",n),e.on("keyboardActivity",n)};(function(){this.updateStatus=function(e){function n(e,n){e&&t.push(e,n||"|")}var t=[];n(e.keyBinding.getStatusText(e)),e.commands.recording&&n("REC");var r=e.selection,i=r.lead;if(!r.isEmpty()){var s=e.getSelectionRange();n("("+(s.end.row-s.start.row)+":"+(s.end.column-s.start.column)+")"," ")}n(i.row+":"+i.column," "),r.rangeCount&&n("["+r.rangeCount+"]"," "),t.pop(),this.element.textContent=t.join("")}}).call(s.prototype),t.StatusBar=s}); 2 | (function() { 3 | ace.require(["ace/ext/statusbar"], function() {}); 4 | })(); 5 | -------------------------------------------------------------------------------- /blue-web/src/main/assets/less/css.less: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // Global variables 4 | @url_images: "../img"; 5 | @url_fonts: "fonts"; 6 | 7 | @pageBackground: #FFF; 8 | @pageWidth: 724px; 9 | @loginPageWidth: 275px; 10 | @loginPageHeight: 425px; 11 | @placeholderColor: #999; 12 | @selectionColor: #A6CBF3; 13 | @font: Helvetica,Arial, sans-serif; 14 | @linkColor: #415FBE; 15 | @fontColor: #333; 16 | @backgroundColor: #EEE; 17 | @headerColor: #FFF; 18 | @headerBackground: #373942; 19 | @headerHeight: 42px; 20 | @headerLinkColor: #F3F3F3; 21 | @buttonColor: #FFF; 22 | @buttonBackground: #50638B; 23 | @buttonStartBackground: #5F7C3A; 24 | @buttonDeleteBackground: #BB4545; 25 | @errorBackground: #BB4545; 26 | @warningBackground: #D68100; 27 | @messageBackground: #6E99F5; 28 | @messageColor: #FFF; 29 | @topMenuBackground: #FAFAFA; 30 | @topMenuColor: #333; 31 | 32 | // Imports all files 33 | @import "ngdialog.css"; 34 | @import "normalize.css"; 35 | @import "main.less"; 36 | @import "login.less"; 37 | @import "paper.less"; 38 | @import "papers.less"; 39 | @import "form_page.less"; 40 | @import "icon.less"; 41 | @import "mobile.less"; 42 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/CompilationStatus.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | 20 | sealed trait CompilationStatus 21 | 22 | case object CompilationSucceeded extends CompilationStatus 23 | 24 | final case class CompilationFailed(pdfProduced: Boolean) extends CompilationStatus 25 | 26 | case object CompilationAborted extends CompilationStatus 27 | 28 | case object CompilationUnnecessary extends CompilationStatus 29 | 30 | -------------------------------------------------------------------------------- /blue-test/src/main/scala/gnieh/blue/Person.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | 18 | case class Person(username: String, first_name: String, last_name: String, email_address: String, affiliation: Option[String]) { 19 | def toMap = Map( 20 | "username" -> username, 21 | "first_name" -> first_name, 22 | "last_name" -> last_name, 23 | "email_address" -> email_address 24 | ) ++ affiliation.map(a => "affiliation" -> a).toMap 25 | 26 | val password = username 27 | 28 | } 29 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/impl/TemplatesImpl.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | package impl 19 | 20 | import gnieh.mustache._ 21 | 22 | class TemplatesImpl(configuration: BlueConfiguration) extends Templates { 23 | 24 | val engine = 25 | new MustacheProcessor(new FileSystemLoader(configuration.templateDir), true) 26 | 27 | def layout(name: String, params: (String, Any)*) = 28 | engine.render(s"$name.mustache", Map(params: _*)) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/lib/ngStorage.min.js: -------------------------------------------------------------------------------- 1 | /*! ngStorage 0.3.0 | Copyright (c) 2013 Gias Kay Lee | MIT License */"use strict";!function(){function a(a){return["$rootScope","$window",function(b,c){for(var d,e,f,g=c[a]||(console.warn("This browser does not support Web Storage!"),{}),h={$default:function(a){for(var b in a)angular.isDefined(h[b])||(h[b]=a[b]);return h},$reset:function(a){for(var b in h)"$"===b[0]||delete h[b];return h.$default(a)}},i=0;i v } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/reset.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 |

5 | To reset your password, enter the username you use to sign in. 6 |

7 |
8 |
9 |
10 |
11 | 12 | 14 |
15 |
17 | 19 |
20 |
21 |
22 | 23 | 26 |
27 |
28 |
-------------------------------------------------------------------------------- /blue-dist/src/shell/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this to install \BlueLaTeX distribution. 4 | 5 | # Where the \BlueLaTeX binaries are installed 6 | INSTALL_DIR=$install_dir 7 | 8 | # Where the \BlueLaTeX configuration files are installed 9 | CONF_DIR=$conf_dir 10 | 11 | # Where the paper data will be stored 12 | DATA_DIR=$data_dir 13 | 14 | # Where the log files are created 15 | LOG_DIR=$log_dir 16 | 17 | # The user under which \BlueLaTeX will run 18 | BLUE_USER=$blue_user 19 | 20 | if [[ -d "$INSTALL_DIR" || -d "$CONF_DIR" || -d "$DATA_DIR" ]] 21 | then 22 | echo "Another version of \\BlueLaTeX seems to be already installed. Please consider using 'update.sh' instead" 23 | exit 1 24 | fi 25 | 26 | # Create directories 27 | mkdir -p $INSTALL_DIR 28 | mkdir -p $CONF_DIR 29 | mkdir -p $DATA_DIR 30 | mkdir -p $LOG_DIR 31 | 32 | # Copy stuffs 33 | cp -r bin bundle $INSTALL_DIR 34 | cp -r conf/* $CONF_DIR 35 | cp -r data/* $DATA_DIR 36 | 37 | # Create the user if needed 38 | id -u $BLUE_USER &>/dev/null 39 | if [ $? -ne 0 ] 40 | then 41 | adduser --system --group --disabled-password --disabled-login --no-create-home $BLUE_USER 42 | fi 43 | 44 | # Set correct ownership 45 | chown -R $BLUE_USER:$BLUE_USER $DATA_DIR $LOG_DIR 46 | 47 | echo "\\BlueLaTeX was successfully installed" 48 | -------------------------------------------------------------------------------- /src/main/designs/blue_papers/papers.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "_design/papers", 3 | "language": "javascript", 4 | "views": { 5 | "authors": { 6 | "map": "function(doc) { if(doc.authors) { emit(doc._id, doc.authors.users); }}" 7 | }, 8 | "reviewers": { 9 | "map": "function(doc) { if(doc.reviewers) { emit(doc._id, doc.reviewers.users); }}" 10 | } 11 | "people": { 12 | "map": "function(doc) { if(doc.authors) { for(i in doc.authors.users) { emit(doc._id, {'role': 'author', '_id': doc.authors.users[i]}); } } if(doc.reviewers) { for(i in doc.reviewers.users) { emit(doc._id, {'_id': doc.reviewers.users[i], 'role': 'reviewer'}); } }}" 13 | } 14 | "for": { 15 | "map": "function(doc) { if(doc.authors) { for(i in doc.authors.users) { emit(doc.authors.users[i], { 'id': doc['sohva-entities-entity'], 'role': 'author' }); } } if(doc.reviewers) { for(i in doc.reviewers.users) { emit(doc.reviewers.users[i], { 'id': doc['sohva-entities-entity'], 'role': 'reviewer' }); } }}" 16 | } 17 | }, 18 | "validate_doc_update": "function(newDoc, oldDoc, userCtx, secObj) { if(oldDoc && oldDoc.authors && oldDoc.authors.length > 0 && userCtx.roles.indexOf('_admin') == -1 && oldDoc.authors.indexOf(userCtx.name) == -1) { throw 'only authors may modify a paper'; } }" 19 | } 20 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/impl/LogServiceFactory.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common.impl 18 | 19 | import org.osgi.framework.{ 20 | Bundle, 21 | ServiceRegistration, 22 | ServiceFactory 23 | } 24 | import org.osgi.service.log.LogService 25 | 26 | class LogServiceFactory extends ServiceFactory[LogService] { 27 | 28 | def getService(bundle: Bundle, registration: ServiceRegistration[LogService]): LogService = 29 | new LogServiceImpl(bundle) 30 | 31 | def ungetService(bundle: Bundle, registration: ServiceRegistration[LogService], service: LogService): Unit = 32 | () // nothing to do 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/permission/Role.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package permission 18 | 19 | /** The different roles for a paper: 20 | * - an author is simply an user listed as such for the paper, 21 | * - a reviewer is an user authenticated user listed as such for the paper, 22 | * - other authenticated users have other role, 23 | * - unauthenticated user get the anonymous role. 24 | * 25 | * @author Lucas Satabin 26 | * 27 | */ 28 | sealed trait Role 29 | case object Author extends Role 30 | case object Reviewer extends Role 31 | case object Other extends Role 32 | case object Guest extends Role 33 | case object Anonymous extends Role 34 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/permission/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | 18 | package object permission { 19 | 20 | // some widely used 'built-in' permissions 21 | 22 | val Publish = Permission("publish") 23 | val Configure = Permission("configure") 24 | val Edit = Permission("edit") 25 | val Delete = Permission("delete") 26 | val Compile = Permission("compile") 27 | val Download = Permission("download") 28 | val Read = Permission("read") 29 | val View = Permission("view") 30 | val Comment = Permission("comment") 31 | val Chat = Permission("chat") 32 | val Fork = Permission("fork") 33 | val ChangePhase = Permission("change-phase") 34 | 35 | } 36 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/User.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue.couch 17 | 18 | import gnieh.sohva._ 19 | 20 | /** A user of blue has the standard fields of couchdb users 21 | * but also contains extra information, specific to blue. 22 | * 23 | * @author Lucas Satabin 24 | * 25 | */ 26 | case class User(name: String, 27 | first_name: String, 28 | last_name: String, 29 | email: String, 30 | affiliation: Option[String] = None) extends IdRev { 31 | 32 | val _id = s"org.couchdb.user:$name:blue" 33 | 34 | def fullName = s"$first_name $last_name" 35 | 36 | } 37 | 38 | case class UserRole(id: String, role: String) 39 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/messages.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
-------------------------------------------------------------------------------- /project/Tests.scala: -------------------------------------------------------------------------------- 1 | package blue 2 | 3 | import sbt._ 4 | import Keys._ 5 | 6 | trait Tests { 7 | this: BlueBuild => 8 | 9 | val Scenario = config("scenario") extend(IntegrationTest) 10 | 11 | lazy val testing = 12 | (Project(id = "blue-test", 13 | base = file("blue-test")) 14 | configs(IntegrationTest, Scenario) 15 | settings( 16 | inConfig(Scenario)(Defaults.itSettings): _* 17 | ) 18 | settings( 19 | inConfig(IntegrationTest)(Defaults.itSettings): _* 20 | ) 21 | settings( 22 | libraryDependencies ++= testDeps, 23 | fork in IntegrationTest := true, 24 | parallelExecution in IntegrationTest := false, 25 | testOptions in IntegrationTest <+= (couchPort in bluelatex, couchAdmin in bluelatex, couchPassword in bluelatex) map { (port, admin, password) => 26 | Tests.Argument(s"-DcouchPort=$port", s"-Dadmin=$admin", s"-Dpassword=$password") 27 | }, 28 | test in Scenario <<= (blueStop in bluelatex) dependsOn ((test in IntegrationTest) dependsOn (blueStart in bluelatex)) 29 | ) 30 | ) dependsOn(blueCommon) 31 | 32 | lazy val testDeps = Seq( 33 | "org.subethamail" % "subethasmtp" % "3.1.7", 34 | "org.scala-stm" %% "scala-stm" % "0.7", 35 | "net.databinder.dispatch" %% "dispatch-core" % "0.11.0", 36 | "org.scalatest" %% "scalatest" % "2.2.0" % "scenario,test,it" 37 | ) 38 | 39 | } 40 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/session/GetSessionDataLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package session 20 | 21 | import com.typesafe.config.Config 22 | 23 | import http._ 24 | import common._ 25 | 26 | import tiscaf._ 27 | 28 | import gnieh.sohva.control.CouchClient 29 | 30 | import scala.util.{ 31 | Try, 32 | Success 33 | } 34 | 35 | /** Get the session data if the request is authenticated. 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class GetSessionDataLet(val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 40 | 41 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Unit] = 42 | Success(talk.writeJson(user)) 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/ext-spellcheck.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event");t.contextMenuHandler=function(e){var t=e.target,n=t.textInput.getElement();if(!t.selection.isEmpty())return;var i=t.getCursorPosition(),s=t.session.getWordRange(i.row,i.column),o=t.session.getTextRange(s);t.session.tokenRe.lastIndex=0;if(!t.session.tokenRe.test(o))return;var u="",a=o+" "+u;n.value=a,n.setSelectionRange(o.length,o.length+1),n.setSelectionRange(0,0),n.setSelectionRange(0,o.length);var f=!1;r.addListener(n,"keydown",function l(){r.removeListener(n,"keydown",l),f=!0}),t.textInput.setInputHandler(function(e){console.log(e,a,n.selectionStart,n.selectionEnd);if(e==a)return"";if(e.lastIndexOf(a,0)===0)return e.slice(a.length);if(e.substr(n.selectionEnd)==a)return e.slice(0,-a.length);if(e.slice(-2)==u){var r=e.slice(0,-2);if(r.slice(-1)==" ")return f?r.substring(0,n.selectionEnd):(r=r.slice(0,-1),t.session.replace(s,r),"")}return e})};var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{spellcheck:{set:function(e){var n=this.textInput.getElement();n.spellcheck=!!e,e?this.on("nativecontextmenu",t.contextMenuHandler):this.removeListener("nativecontextmenu",t.contextMenuHandler)},value:!0}})}); 2 | (function() { 3 | ace.require(["ace/ext/spellcheck"], function() {}); 4 | })(); 5 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/ext-themelist.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"],function(e,t,n){"use strict";e("ace/lib/fixoldbrowsers");var r=[["Chrome"],["Clouds"],["Crimson Editor"],["Dawn"],["Dreamweaver"],["Eclipse"],["GitHub"],["IPlastic"],["Solarized Light"],["TextMate"],["Tomorrow"],["XCode"],["Kuroir"],["KatzenMilch"],["SQL Server","sqlserver","light"],["Ambiance","ambiance","dark"],["Chaos","chaos","dark"],["Clouds Midnight","clouds_midnight","dark"],["Cobalt","cobalt","dark"],["idle Fingers","idle_fingers","dark"],["krTheme","kr_theme","dark"],["Merbivore","merbivore","dark"],["Merbivore Soft","merbivore_soft","dark"],["Mono Industrial","mono_industrial","dark"],["Monokai","monokai","dark"],["Pastel on dark","pastel_on_dark","dark"],["Solarized Dark","solarized_dark","dark"],["Terminal","terminal","dark"],["Tomorrow Night","tomorrow_night","dark"],["Tomorrow Night Blue","tomorrow_night_blue","dark"],["Tomorrow Night Bright","tomorrow_night_bright","dark"],["Tomorrow Night 80s","tomorrow_night_eighties","dark"],["Twilight","twilight","dark"],["Vibrant Ink","vibrant_ink","dark"]];t.themesByName={},t.themes=r.map(function(e){var n=e[1]||e[0].replace(/ /g,"_").toLowerCase(),r={caption:e[0],theme:"ace/theme/"+n,isDark:e[2]=="dark",name:n};return t.themesByName[n]=r,r})}); 2 | (function() { 3 | ace.require(["ace/ext/themelist"], function() {}); 4 | })(); 5 | -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/SyncApi.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | package impl 19 | 20 | import http._ 21 | import common._ 22 | import let._ 23 | 24 | import com.typesafe.config.Config 25 | 26 | import gnieh.sohva.control.CouchClient 27 | 28 | /** The synchronization service API exposes an interface for clients 29 | * to synchronize their paper 30 | * 31 | * @author Lucas Satabin 32 | */ 33 | class SyncApi(couch: CouchClient, val config: Config, synchroServer: SynchroServer, logger: Logger) extends RestApi { 34 | 35 | POST { 36 | case p"papers/$paperid/q" => 37 | new QLet(paperid, synchroServer, couch, config, logger) 38 | case p"papers/$paperid/sync" => 39 | new SynchronizePaperLet(paperid, synchroServer, couch, config, logger) 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/Logging.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | import org.osgi.service.log.LogService 20 | 21 | /** Mixin this trait in any class you want to have support for logging 22 | * 23 | * @author Lucas Satabin 24 | * 25 | */ 26 | trait Logging { 27 | 28 | import LogService._ 29 | 30 | val logger: Logger 31 | 32 | @inline 33 | def logDebug(msg: String): Unit = 34 | logger.log(LOG_DEBUG, msg) 35 | 36 | @inline 37 | def logInfo(msg: String): Unit = 38 | logger.log(LOG_INFO, msg) 39 | 40 | @inline 41 | def logWarn(msg: String): Unit = 42 | logger.log(LOG_WARNING, msg) 43 | 44 | @inline 45 | def logError(msg: String, exn: Throwable): Unit = 46 | logger.log(LOG_ERROR, msg, exn) 47 | 48 | @inline 49 | def logError(msg: String): Unit = 50 | logger.log(LOG_ERROR, msg) 51 | 52 | } 53 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/shared/controllers/MessagesController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | angular.module('bluelatex.Shared.Controllers.Messages', ['bluelatex.Shared.Services.Messages']) 20 | .controller('MessagesController', [ 21 | '$rootScope', 22 | '$scope', 23 | 'MessagesService', 24 | function ($rootScope, 25 | $scope, 26 | MessagesService) { 27 | // give access to messages, warnings and errors 28 | $scope.messages = MessagesService.messages; 29 | $scope.warnings = MessagesService.warnings; 30 | $scope.errors = MessagesService.errors; 31 | 32 | $scope.messagesSession = MessagesService.messagesSession; 33 | $scope.warningsSession = MessagesService.warningsSession; 34 | $scope.errorsSession = MessagesService.errorsSession; 35 | 36 | $scope.close = MessagesService.close; 37 | } 38 | ]); -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/store/Store.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | package impl 19 | package store 20 | 21 | /** Describes the interface that all stores must implement. 22 | * A store allows user to persist a document. It may be e.g. a file on the file system, 23 | * a database, ... 24 | * 25 | * @author Lucas Satabin 26 | */ 27 | trait Store { 28 | 29 | /** Persists the document in the store. Create it if it does not exist yet. */ 30 | def save(document: Document) 31 | 32 | /** Loads the document from the store, if it does not exist, returns empty Document. */ 33 | def load(documentId: String): Document 34 | 35 | /** Delete the document from the store. */ 36 | def delete(document: Document) 37 | 38 | } 39 | 40 | class StoreException(msg: String, inner: Throwable) extends Exception(msg, inner) { 41 | def this(msg: String) = this(msg, null) 42 | } 43 | -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/EditCommandParser.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | package impl 19 | 20 | import scala.util.parsing.combinator._ 21 | 22 | /** A simple parser for Edit commands. 23 | * @author Lucas Satabin 24 | * 25 | */ 26 | object EditCommandParsers extends RegexParsers { 27 | 28 | override def skipWhitespace = false 29 | 30 | /** Parse unencoded string into Edit object */ 31 | def parseEdit(input: String): Option[Edit] = 32 | parseAll(edit, input) match { 33 | case Success(res, _) => Some(res) 34 | case f => None 35 | } 36 | 37 | lazy val edit: Parser[Edit] = 38 | ("+" ~> data ^^ Add 39 | | "-" ~> number ^^ Delete 40 | | "=" ~> number ^^ Equality) 41 | 42 | private lazy val number: Parser[Int] = 43 | "[0-9]+".r ^^ (_.toInt) 44 | 45 | private lazy val data: Parser[String] = 46 | "(?s).*".r 47 | 48 | } 49 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/paper/latex/reviewer.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | Download 6 |
7 |
8 |
9 |
10 | 19 |
20 | 27 |
28 |
29 |
30 |
40 |
41 |
-------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/PaperConfiguration.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | import com.typesafe.config.Config 20 | 21 | import java.io.File 22 | 23 | class PaperConfiguration(val config: Config) { 24 | 25 | import FileUtils._ 26 | 27 | def paperDir(paperId: String): File = 28 | new File(config.getString("blue.paper.directory")) / paperId 29 | 30 | def paperFile(paperId: String): File = 31 | paperDir(paperId) / "main.tex" 32 | 33 | def resource(paperId: String, resourceName: String): File = 34 | paperDir(paperId) / resourceName 35 | 36 | def bibFile(paperId: String): File = 37 | paperDir(paperId) / "references.bib" 38 | 39 | def clsDir: File = 40 | new File(config.getString("blue.paper.classes")) 41 | 42 | def clsFiles: List[File] = 43 | clsDir.filter(_.getName.endsWith(".cls")) 44 | 45 | def cls(name: String): File = 46 | clsDir / s"$name.cls" 47 | 48 | } 49 | -------------------------------------------------------------------------------- /blue-mobwrite/src/main/scala/gnieh/blue/mobwrite/MobwriteActivator.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package mobwrite 18 | 19 | import org.osgi.framework._ 20 | 21 | import common._ 22 | 23 | /** Registers the mobwrite service that delegates synchronization 24 | * to a standalone process 25 | * 26 | * @author Lucas Satabin 27 | */ 28 | class MobwriteActivator extends BundleActivator { 29 | 30 | import common.OsgiUtils._ 31 | 32 | def start(context: BundleContext): Unit = { 33 | for(loader <- context.get[ConfigurationLoader]) { 34 | // instantiate the mobwrite server as synchronization server 35 | val server = new MobwriteServer(loader.load(context.getBundle.getSymbolicName, getClass.getClassLoader)) 36 | // register this as the synchronization server 37 | context.registerService(classOf[SynchroServer], server, null) 38 | } 39 | } 40 | 41 | def stop(context: BundleContext): Unit = { 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/let/GetCompilersLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | package let 20 | 21 | import http._ 22 | import common._ 23 | 24 | import tiscaf._ 25 | 26 | import com.typesafe.config.Config 27 | 28 | import org.osgi.framework.BundleContext 29 | 30 | import scala.util.Try 31 | 32 | import gnieh.sohva.control.CouchClient 33 | 34 | /** Returns the list of compilers that are currently available in \BlueLaTeX 35 | * and that can be used to compile the papers 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class GetCompilersLet(context: BundleContext, val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 40 | 41 | import OsgiUtils._ 42 | 43 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Any] = 44 | Try(talk.writeJson(context.getAll[Compiler].map(_.name).toList.sorted)) 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/shared/directives/LocalizeTooltipDirective.js: -------------------------------------------------------------------------------- 1 | angular.module('bluelatex.Shared.Directives.tooltip', ['ngTooltip']) 2 | .directive('i18nTooltip',[ '$tooltip', 'localize', 3 | function($tooltip, localize) { 4 | return { 5 | restrict: 'EA', 6 | scope: { 7 | content: '@i18nTooltip', 8 | }, 9 | link: function(scope, elem, attr) { 10 | /** 11 | * Translate the message 12 | */ 13 | var getMessageLocalized = function (m) { 14 | var tempMessage = localize.getLocalizedString(m); 15 | if(tempMessage == '' || tempMessage == null) { 16 | tempMessage = m.replace(/_/g,' ').trim(); 17 | } 18 | return tempMessage; 19 | }; 20 | 21 | var tooltip = $tooltip({ 22 | target: elem, 23 | scope: scope, 24 | tether: { 25 | attachment: 'middle left', 26 | targetAttachment: 'middle right', 27 | constraints: [ 28 | { 29 | to: document.getElementById('page'), 30 | attachment: 'together', 31 | pin: true 32 | } 33 | ] 34 | } 35 | }); 36 | 37 | var displayTimeout = null; 38 | elem[0].onmouseover = function() { 39 | displayTimeout = setTimeout(function () { 40 | scope.content = getMessageLocalized(scope.content); 41 | scope.$apply(tooltip.open); 42 | }, 250); 43 | }; 44 | elem[0].onmouseout = function() { 45 | clearTimeout(displayTimeout); 46 | scope.$apply(tooltip.close); 47 | }; 48 | } 49 | }; 50 | }]); -------------------------------------------------------------------------------- /blue-compile/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | # The *TeX system process configuration keys 2 | tex { 3 | 4 | # compilation processes are launched in a pool of available processes. 5 | # the size of the available process pool is configurable here. 6 | 7 | # the minimum amount of available processes in the process pool 8 | min-process = 5 9 | 10 | # the maximum amount of *TeX processes that can run in parallel 11 | max-process = 100 12 | 13 | } 14 | 15 | # The default compiler configuration keys 16 | compiler { 17 | 18 | # whether the compilation task is started in background, or 19 | # started explicitly by people. 20 | # Possible values are: 21 | # - `background` means that papers are compiled regularly with a background 22 | # task started. 23 | # - `explicit` means that paper compilation must be triggered explicitly by 24 | # users to be performed. 25 | compilation-type = explicit 26 | 27 | # the default compiler used when creating \LaTeX paper 28 | default = pdflatex 29 | 30 | # whether SyncTeX data are generated by default for newly created papers 31 | synctex = true 32 | 33 | # the timeout after which compilation process for the paper must be aborted 34 | timeout = 30 seconds 35 | 36 | # interval of time to wait between two runs of the compiler 37 | # if the `compilation-type` is `background`, this is the time the background 38 | # task waits between the end of a compilation run and the next one to start. 39 | # if the `compilation-type` is `explicit`, this is the minimum amount of time 40 | # a user must wait between two compilation requests. 41 | interval = 1 second 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/templates/sigproc-sp.tex.mustache: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | % template for Strict Adherence to SIGS style. 3 | % for more explanations look at http://www.acm.org/sigs/publications/proceedings-templates#aL1 4 | 5 | \documentclass{sigproc-sp} 6 | 7 | \begin{document} 8 | 9 | \title{<% title %>} 10 | 11 | \numberofauthors{2} 12 | 13 | \author{ 14 | % 1st. author 15 | \alignauthor 16 | <% author %>\\ 17 | \affaddr{<% affiliation %>}\\ 18 | \affaddr{Street}\\ 19 | \affaddr{City, Country}\\ 20 | \email{<% email %>} 21 | % 2nd. author 22 | \alignauthor 23 | Your Co-Author\\ 24 | \affaddr{Institute}\\ 25 | \affaddr{Street}\\ 26 | \affaddr{City, Country}\\ 27 | \email{second.author@email.com} 28 | } 29 | 30 | \maketitle 31 | \begin{abstract} 32 | This is the abstract. 33 | \end{abstract} 34 | 35 | % A category with the (minimum) three required fields 36 | \category{H.4}{Information Systems Applications}{Miscellaneous} 37 | %A category including the fourth, optional field follows... 38 | \category{D.2.8}{Software Engineering}{Metrics}[complexity measures, performance measures] 39 | 40 | \terms{Template} 41 | 42 | \keywords{ACM proceedings, \LaTeX, text tagging} 43 | 44 | \section{Introduction} 45 | Your wonderful introduction 46 | 47 | \section{Remainder of Your Paper} 48 | 49 | blablabla 50 | 51 | % 52 | % The following two commands are all you need in the 53 | % initial runs of your .tex file to 54 | % produce the bibliography for the citations in your paper. 55 | %\bibliographystyle{abbrv} 56 | %\bibliography{references} 57 | 58 | \end{document} 59 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/session/LogoutLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package session 20 | 21 | import com.typesafe.config.Config 22 | 23 | import http._ 24 | import common._ 25 | 26 | import tiscaf._ 27 | 28 | import scala.util.Try 29 | 30 | import gnieh.sohva.control.CouchClient 31 | 32 | /** Log the user in. 33 | * It delegates to the CouchDB login system and keeps track of the CouchDB cookie 34 | * 35 | * @author Lucas Satabin 36 | */ 37 | class LogoutLet(val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) { 38 | 39 | def act(talk: HTalk): Try[Unit] = 40 | couchSession(talk).logout map { 41 | case true => 42 | talk.ses.invalidate 43 | talk.writeJson(true) 44 | case false => 45 | talk 46 | .setStatus(HStatus.InternalServerError) 47 | .writeJson(ErrorResponse("unable_to_logout", "Unable to log user out")) 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/compiler/XelatexCompiler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | package compiler 20 | 21 | import common._ 22 | 23 | import akka.actor.ActorSystem 24 | import akka.util.Timeout 25 | 26 | import scala.concurrent._ 27 | 28 | import scala.util.Try 29 | 30 | import java.io.File 31 | 32 | import com.typesafe.config.Config 33 | 34 | /** Compiles a project with `xelatex` and `bibtex` 35 | * 36 | * @author Lucas Satabin 37 | */ 38 | class XelatexCompiler(system: ActorSystem, config: Config, configDir: File) extends SystemCompiler(system, config, configDir) { 39 | 40 | val name: String = "xelatex" 41 | 42 | def compile(paperId: String, settings: CompilerSettings)(implicit timeout: Timeout): Try[Boolean] = 43 | exec(s"xelatex -interaction nonstopmode -synctex=${if(settings.synctex) 1 else 0} -output-directory ${buildDir(paperId)} ${paperFile(paperId)}", 44 | configuration.paperDir(paperId)) //, List("TEXINPUT" -> ".:tex/:resources/:$TEXINPUTS")) 45 | 46 | } 47 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/compiler/LualatexCompiler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | package compiler 20 | 21 | import common._ 22 | 23 | import akka.actor.ActorSystem 24 | import akka.util.Timeout 25 | 26 | import scala.concurrent._ 27 | 28 | import scala.util.Try 29 | 30 | import java.io.File 31 | 32 | import com.typesafe.config.Config 33 | 34 | /** Compiles a project with `lualatex` and `bibtex` 35 | * 36 | * @author Lucas Satabin 37 | */ 38 | class LualatexCompiler(system: ActorSystem, config: Config, configDir: File) extends SystemCompiler(system, config, configDir) { 39 | 40 | val name: String = "lualatex" 41 | 42 | def compile(paperId: String, settings: CompilerSettings)(implicit timeout: Timeout): Try[Boolean] = 43 | exec(s"lualatex -interaction nonstopmode -synctex=${if(settings.synctex) 1 else 0} -output-directory ${buildDir(paperId)} ${paperFile(paperId)}", 44 | configuration.paperDir(paperId)) //, List("TEXINPUT" -> ".:tex/:resources/:$TEXINPUTS")) 45 | 46 | } 47 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/compiler/PdflatexCompiler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | package compiler 20 | 21 | import common._ 22 | 23 | import akka.actor.ActorSystem 24 | import akka.util.Timeout 25 | 26 | import scala.concurrent._ 27 | 28 | import scala.util.Try 29 | 30 | import java.io.File 31 | 32 | import com.typesafe.config.Config 33 | 34 | /** Compiles a project with `pdflatex` and `bibtex` 35 | * 36 | * @author Lucas Satabin 37 | */ 38 | class PdflatexCompiler(system: ActorSystem, config: Config, configDir: File) extends SystemCompiler(system, config, configDir) { 39 | 40 | val name: String = "pdflatex" 41 | 42 | def compile(paperId: String, settings: CompilerSettings)(implicit timeout: Timeout): Try[Boolean] = 43 | exec(s"pdflatex -interaction nonstopmode -synctex=${if(settings.synctex) 1 else 0} -output-directory ${buildDir(paperId)} ${paperFile(paperId)}", 44 | configuration.paperDir(paperId)) //, List("TEXINPUT" -> ".:tex/:resources/:$TEXINPUTS")) 45 | 46 | } 47 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/login.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 |
7 |
9 | 11 | 13 | 15 |
16 |
18 | 20 | 22 |
23 |
24 | 28 | 29 | 30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /blue-web/src/main/scala/gnieh/blue/web/WebApp.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package web 18 | 19 | import tiscaf._ 20 | 21 | import org.osgi.framework.BundleContext 22 | 23 | import com.typesafe.config.Config 24 | 25 | /** This web application serves static web client 26 | * 27 | * @author Lucas Satabin 28 | */ 29 | class WebApp(context: BundleContext, config: Config) extends HApp { 30 | 31 | // this is required by the resource let used to serve static content 32 | override val buffered = true 33 | 34 | private val Prefix = "/*(.*)/*".r 35 | 36 | private val prefix = config.getString("blue.client.path-prefix") match { 37 | case Prefix(prefix) => prefix 38 | case _ => "" 39 | } 40 | 41 | private val configLet = new ConfigLet(context, config) 42 | private val webLet = new WebLet(context, prefix) 43 | 44 | private val configPath = 45 | s"${if(prefix.nonEmpty) prefix + "/" else ""}configuration" 46 | 47 | def resolve(req: HReqData) = 48 | if(req.uriPath == configPath) 49 | Some(configLet) 50 | else 51 | Some(webLet) 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/lib/angular/angular-loader.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.5.6 3 | (c) 2010-2016 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(){'use strict';function d(b){return function(){var a=arguments[0],e;e="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.5.6/"+(b?b+"/":"")+a;for(a=1;a 49 | logger.log(LogService.LOG_ERROR, s"Unable to start the web client bundle", e) 50 | throw e 51 | } 52 | 53 | def stop(context: BundleContext): Unit = { 54 | } 55 | 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/SynchroServer.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | import scala.util.Try 20 | 21 | import java.util.Date 22 | 23 | /** Synchronization server interface 24 | * 25 | * @author Lucas Satabin 26 | */ 27 | trait SynchroServer { 28 | 29 | /** Starts a new session with the data and returns 30 | * the result data for the client 31 | */ 32 | def session(data: String): Try[String] 33 | 34 | /** Persists the synchronized files for the given paper 35 | * This call is synchronous and only returns when all files 36 | * are synchronized 37 | */ 38 | def persist(paperId: String): Unit 39 | 40 | /** Retrieve the last modification date of a paper. 41 | * This date is updated every time a synchronized file of a paper 42 | * (ie, associated to `paperId`) is updated. 43 | * This call is synchronous. 44 | */ 45 | def lastModificationDate(paperId: String): Date 46 | } 47 | 48 | /** Exception used in case of failure of the session() method. 49 | */ 50 | class SynchroFailureException(msg: String, inner: Throwable) extends Exception(msg, inner) { 51 | def this(msg: String) = this(msg, null) 52 | } 53 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/user/GetUserInfoLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package user 20 | 21 | import http._ 22 | import couch.User 23 | import common._ 24 | 25 | import com.typesafe.config.Config 26 | 27 | import tiscaf._ 28 | 29 | import gnieh.sohva.control.CouchClient 30 | 31 | import scala.io.Source 32 | 33 | import scala.util.Try 34 | 35 | /** Returns the user data 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class GetUserInfoLet(username: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 40 | 41 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Unit] = 42 | // only authenticated users may see other people information 43 | entityManager("blue_users").getComponent[User](s"org.couchdb.user:$username") map { 44 | // we are sure that the user has a revision because it comes from the database 45 | case Some(user) => talk.writeJson(user, user._rev.get) 46 | case None => talk.setStatus(HStatus.NotFound).writeJson(ErrorResponse("not_found", s"No user named $username found")) 47 | } 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/user/GetUsersLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package user 20 | 21 | import http._ 22 | import couch.User 23 | import common._ 24 | 25 | import com.typesafe.config.Config 26 | 27 | import tiscaf._ 28 | 29 | import gnieh.sohva.UserInfo 30 | 31 | import scala.io.Source 32 | 33 | import scala.util.Try 34 | 35 | import gnieh.sohva.control.CouchClient 36 | 37 | /** Return a (potentially filtered) list of user names. 38 | * 39 | * @author Lucas Satabin 40 | */ 41 | class GetUsersLet(val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 42 | 43 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Any] = { 44 | val userNames = view(blue_users, "lists", "names") 45 | // get the filter parameter if any 46 | val filter = talk.req.param("name") 47 | val startkey = filter.map(_.toLowerCase) 48 | val endkey = startkey.map(_.toLowerCase + "Z") 49 | for(users <- userNames.query[String, String, Any](startkey = startkey, endkey = endkey)) 50 | yield talk.writeJson(users.rows.map(_.key)) 51 | } 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/user/controllers/LogoutUserController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | angular.module("bluelatex.User.Controllers.Logout",['bluelatex.User.Services.Session','bluelatex.User.Services.User']) 18 | .controller('LogoutController', [ 19 | '$rootScope', 20 | 'SessionService', 21 | 'UserService', 22 | '$location', 23 | 'MessagesService', 24 | function ($rootScope, 25 | SessionService, 26 | UserService, 27 | $location, 28 | MessagesService) { 29 | 30 | MessagesService.clear(); 31 | /* 32 | * Logout the user 33 | */ 34 | SessionService.logout().then(function (data) { 35 | $rootScope.loggedUser = {}; 36 | UserService.clearCache(); 37 | $location.path("/login"); 38 | }, function (err) { 39 | switch (err.status) { 40 | case 401: 41 | MessagesService.error('_Logout_Not_connected_',err); 42 | break; 43 | case 500: 44 | MessagesService.error('_Logout_Something_wrong_happened_',err); 45 | break; 46 | default: 47 | MessagesService.error('_Logout_Something_wrong_happened_',err); 48 | } 49 | }); 50 | } 51 | ]); -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/menu.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 15 | 25 | 32 | 38 |
39 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/impl/DbManager.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package couch 18 | package impl 19 | 20 | import common._ 21 | 22 | import gnieh.sohva.control._ 23 | 24 | /** the database manager is in charge of database creation and designs management. 25 | * 26 | * @author Lucas Satabin 27 | */ 28 | class DbManager(client: CouchClient, configuration: CouchConfiguration, val logger: Logger) extends Logging { 29 | 30 | /** Starts the database manager. 31 | * It creates the databases that need to be created and update all 32 | * needed design documents 33 | */ 34 | def start() { 35 | configuration.asAdmin(client) { session => 36 | configuration.databases.foreach { db => 37 | try { 38 | // first create inexistent databases 39 | val database = session.database(db, credit = 1) 40 | database.create 41 | // then create the design manager and update design documents 42 | val dm = new DesignManager(configuration, database, logger) 43 | dm.reload 44 | } catch { 45 | case e: Exception => // ignore exception 46 | logError("Cannot save design documents", e) 47 | } 48 | } 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/http/impl/RestServiceTracker.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package http 18 | package impl 19 | 20 | import tiscaf._ 21 | 22 | import org.osgi.framework._ 23 | import org.osgi.util.tracker.ServiceTracker 24 | 25 | import scala.collection.mutable.Map 26 | 27 | /** Tracks the `RestHandler` services that are (un)registered to dynamically extend 28 | * the server interface 29 | * 30 | * @author Lucas Satabin 31 | */ 32 | class RestServiceTracker(context: BundleContext, app: ExtensibleApp) 33 | extends ServiceTracker[RestApi, Long](context, classOf[RestApi], null) { 34 | 35 | override def addingService(ref: ServiceReference[RestApi]): Long = { 36 | // get the service instance 37 | val service = context.getService(ref) 38 | // get the servive identifier 39 | val id = ref.getProperty(Constants.SERVICE_ID).asInstanceOf[Long] 40 | app.synchronized { 41 | // register the rest interface with the generated identifier 42 | app.apps(id) = service 43 | } 44 | id 45 | } 46 | 47 | override def removedService(ref: ServiceReference[RestApi], id: Long): Unit = app.synchronized { 48 | // unregister the handlers for the given identifier 49 | app.apps -= id 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-xcode.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/xcode",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-xcode",t.cssText=".ace-xcode .ace_gutter {background: #e8e8e8;color: #333}.ace-xcode .ace_print-margin {width: 1px;background: #e8e8e8}.ace-xcode {background-color: #FFFFFF;color: #000000}.ace-xcode .ace_cursor {color: #000000}.ace-xcode .ace_marker-layer .ace_selection {background: #B5D5FF}.ace-xcode.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FFFFFF;}.ace-xcode .ace_marker-layer .ace_step {background: rgb(198, 219, 174)}.ace-xcode .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #BFBFBF}.ace-xcode .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.071)}.ace-xcode .ace_gutter-active-line {background-color: rgba(0, 0, 0, 0.071)}.ace-xcode .ace_marker-layer .ace_selected-word {border: 1px solid #B5D5FF}.ace-xcode .ace_constant.ace_language,.ace-xcode .ace_keyword,.ace-xcode .ace_meta,.ace-xcode .ace_variable.ace_language {color: #C800A4}.ace-xcode .ace_invisible {color: #BFBFBF}.ace-xcode .ace_constant.ace_character,.ace-xcode .ace_constant.ace_other {color: #275A5E}.ace-xcode .ace_constant.ace_numeric {color: #3A00DC}.ace-xcode .ace_entity.ace_other.ace_attribute-name,.ace-xcode .ace_support.ace_constant,.ace-xcode .ace_support.ace_function {color: #450084}.ace-xcode .ace_fold {background-color: #C800A4;border-color: #000000}.ace-xcode .ace_entity.ace_name.ace_tag,.ace-xcode .ace_support.ace_class,.ace-xcode .ace_support.ace_type {color: #790EAD}.ace-xcode .ace_storage {color: #C900A4}.ace-xcode .ace_string {color: #DF0002}.ace-xcode .ace_comment {color: #008E00}.ace-xcode .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/JoinPaperLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import http._ 22 | import common._ 23 | import permission._ 24 | 25 | import com.typesafe.config.Config 26 | 27 | import akka.actor.ActorSystem 28 | 29 | import tiscaf._ 30 | 31 | import scala.util.Try 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Notify the system that the user joined a given paper 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class JoinPaperLet( 40 | paperId: String, 41 | peerId: String, 42 | system: ActorSystem, 43 | val couch: CouchClient, 44 | config: Config, 45 | logger: Logger) 46 | extends SyncPermissionLet(paperId, config, logger) { 47 | 48 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = Try { 49 | permissions match { 50 | case Edit() | Read() => 51 | system.eventStream.publish(Join(peerId, paperId)) 52 | talk.writeJson(true) 53 | case _ => 54 | talk 55 | .setStatus(HStatus.Unauthorized) 56 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to join the paper")) 57 | } 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/SynchronizedResourcesLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import com.typesafe.config.Config 22 | 23 | import tiscaf._ 24 | 25 | import http._ 26 | import common._ 27 | import permission._ 28 | 29 | import scala.io.Source 30 | 31 | import scala.util.Try 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Gives access to the synchronized resource list for the given paper. 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class SynchronizedResourcesLet(paperId: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncPermissionLet(paperId, config, logger) { 40 | 41 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = Try(permissions match { 42 | case Edit() => 43 | import FileUtils._ 44 | val files = configuration.paperDir(paperId).filter(_.extension.matches(synchronizedExt)).map(_.getName) 45 | talk.writeJson(files) 46 | case _ => 47 | talk 48 | .setStatus(HStatus.Forbidden) 49 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to see the list of synchronized resources")) 50 | }) 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/snippets/latex.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/snippets/latex",["require","exports","module"],function(e,t,n){"use strict";t.snippets=[{"name":"\\begin{array}...","content":"\\begin{array}{${1:cc}}\n$2 & $3 \\\\\\\\\n$4 & $5\n\\end{array}"},{"name":"\\begin{figure}...","content":"\\begin{figure}\n\\centering\n\\includegraphics{$1}\n\\caption{${2:Caption}}\n\\label{${3:fig:my_label}}\n\\end{figure}"},{"name":"\\begin{tabular}...","content":"\\begin{tabular}{${1:c|c}}\n$2 & $3 \\\\\\\\\n$4 & $5\n\\end{tabular}"},{"name":"\\begin{table}...","content":"\\begin{table}[$1]\n\\centering\n\\begin{tabular}{${2:c|c}}\n$3 & $4 \\\\\\\\\n$5 & $6\n\\end{tabular}\n\\caption{${7:Caption}}\n\\label{${8:tab:my_label}}\n\\end{table}"},{"name":"\\begin{list}...","content":"\\begin{list}\n\\item $1\n\\end{list}"},{"name":"\\begin{enumerate}...","content":"\\begin{enumerate}\n\\item $1\n\\end{enumerate}"},{"name":"\\begin{itemize}...","content":"\\begin{itemize}\n\\item $1\n\\end{itemize}"},{"name":"\\begin{frame}...","content":"\\begin{frame}{${1:Frame Title}}\n$2\n\\end{frame}"},{"name":"\\begin{abstract}...","content":"\\begin{abstract}\n$1\n\\end{abstract}"},{"name":"\\begin{align}...","content":"\\begin{align}\n$1\n\\end{align}"},{"name":"\\begin{align*}...","content":"\\begin{align*}\n$1\n\\end{align*}"},{"name":"\\begin{equation}...","content":"\\begin{equation}\n$1\n\\end{equation}"},{"name":"\\begin{equation*}...","content":"\\begin{equation*}\n$1\n\\end{equation*}"},{"name":"\\begin{gather}...","content":"\\begin{gather}\n$1\n\\end{gather}"},{"name":"\\begin{gather*}...","content":"\\begin{gather*}\n$1\n\\end{gather*}"},{"name":"\\begin{multline}...","content":"\\begin{multline}\n$1\n\\end{multline}"},{"name":"\\begin{multline*}...","content":"\\begin{multline*}\n$1\n\\end{multline*}"},{"name":"\\begin{split}...","content":"\\begin{split}\n$1\n\\end{split}"},{"name":"\\begin{verbatim}...","content":"\\begin{verbatim}\n$1\n\\end{verbatim}"}],t.scope="latex"}) -------------------------------------------------------------------------------- /src/main/templates/sig-alternate.tex.mustache: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | % template for Tighter Alternate style 3 | % for more explanations look at http://www.acm.org/sigs/publications/proceedings-templates#aL2 4 | 5 | \documentclass{sig-alternate} 6 | 7 | \begin{document} 8 | % 9 | \conferenceinfo{WOODSTOCK}{'97 El Paso, Texas USA} 10 | %\CopyrightYear{2007} % Allows default copyright year (20XX) to be over-ridden - IF NEED BE. 11 | %\crdata{0-12345-67-8/90/01} % Allows default copyright data (0-89791-88-6/97/05) to be over-ridden - IF NEED BE. 12 | % --- End of Author Metadata --- 13 | 14 | \title{<% title %>} 15 | 16 | \numberofauthors{2} 17 | 18 | \author{ 19 | % 1st. author 20 | \alignauthor 21 | <% author %>\\ 22 | \affaddr{<% affiliation %>}\\ 23 | \affaddr{Street}\\ 24 | \affaddr{City, Country}\\ 25 | \email{<% email %>} 26 | % 2nd. author 27 | \alignauthor 28 | Your Co-Author\\ 29 | \affaddr{Institute}\\ 30 | \affaddr{Street}\\ 31 | \affaddr{City, Country}\\ 32 | \email{second.author@email.com} 33 | } 34 | 35 | \maketitle 36 | \begin{abstract} 37 | This is the abstract. 38 | \end{abstract} 39 | 40 | % A category with the (minimum) three required fields 41 | \category{H.4}{Information Systems Applications}{Miscellaneous} 42 | %A category including the fourth, optional field follows... 43 | \category{D.2.8}{Software Engineering}{Metrics}[complexity measures, performance measures] 44 | 45 | \terms{Theory} 46 | 47 | \keywords{ACM proceedings, \LaTeX, text tagging} 48 | 49 | \section{Introduction} 50 | Your wonderful introduction 51 | 52 | \section{Remainder of Your Paper} 53 | 54 | blablabla 55 | 56 | % 57 | % The following two commands are all you need in the 58 | % initial runs of your .tex file to 59 | % produce the bibliography for the citations in your paper. 60 | %\bibliographystyle{abbrv} 61 | %\bibliography{references} 62 | 63 | \end{document} 64 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/DeleteResourceLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import com.typesafe.config.Config 22 | 23 | import common._ 24 | import http._ 25 | import permission._ 26 | 27 | import tiscaf._ 28 | 29 | import resource._ 30 | 31 | import scala.util.Try 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Deletes some resource associated to the paper. 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class DeleteResourceLet(paperId: String, resourceName: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncPermissionLet(paperId, config, logger) { 40 | 41 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = Try(permissions match { 42 | case Edit() => 43 | // only authors may get a resource 44 | val file = configuration.resource(paperId, resourceName) 45 | 46 | // delete the file 47 | val ok = file.delete 48 | 49 | // just say OK 50 | talk.writeJson(ok) 51 | 52 | case _ => 53 | talk 54 | .setStatus(HStatus.Forbidden) 55 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to delete resources")) 56 | }) 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/user/SaveUserPermissionsLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package user 20 | 21 | import http._ 22 | import couch.UserPermissions 23 | 24 | import common._ 25 | 26 | import com.typesafe.config.Config 27 | 28 | import tiscaf._ 29 | 30 | import gnieh.sohva.control.CouchClient 31 | 32 | import scala.io.Source 33 | 34 | import scala.util.Try 35 | 36 | /** Save the user permissions with the given name. 37 | * 38 | * @author Lucas Satabin 39 | */ 40 | class SaveUserPermissionsLet(username: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 41 | 42 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Any] = { 43 | val namesOnly = talk.req.param("names_only").map(_ == "true").getOrElse(false) 44 | val manager = entityManager("blue_users") 45 | for(perms <- manager.getComponent[UserPermissions](f"org.couchdb.user:${user.name}")) 46 | yield perms match { 47 | case Some(p @ UserPermissions(_, perms)) => 48 | if(namesOnly) 49 | talk.writeJson(perms.keys, p._rev.get) 50 | else 51 | talk.writeJson(perms, p._rev.get) 52 | case None => 53 | talk.writeJson(Nil) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/BlueConfiguration.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | 19 | import java.util.Properties 20 | 21 | import gnieh.sohva.control._ 22 | 23 | import com.typesafe.config._ 24 | 25 | import scala.collection.JavaConverters._ 26 | 27 | import java.io.{ 28 | File, 29 | FileNotFoundException 30 | } 31 | 32 | class BlueConfiguration(config: Config) extends PaperConfiguration(config) { 33 | 34 | // ===== blue core settings ===== 35 | 36 | val blue = config.getConfig("blue") 37 | 38 | val recaptchaPrivateKey = optionalString("recaptcha.private-key") 39 | 40 | // ===== couchdb settings ===== 41 | 42 | val couch = new CouchConfiguration(config) 43 | 44 | // ===== email settings ===== 45 | 46 | val emailConf = { 47 | val props = new Properties 48 | for(entry <- config.getConfig("mail").entrySet.asScala) { 49 | props.setProperty("mail." + entry.getKey, entry.getValue.unwrapped.toString) 50 | } 51 | props 52 | } 53 | 54 | // ===== templates ===== 55 | 56 | val templateDir = 57 | new File(config.getString("blue.template.directory")) 58 | 59 | // ===== internals ===== 60 | 61 | private def optionalString(path: String): Option[String] = 62 | if(config.hasPath(path)) 63 | Some(config.getString(path)) 64 | else 65 | None 66 | 67 | } 68 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/partials/resetPassword.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 |
5 |
6 |
7 |
8 | 9 | 11 |
12 |
14 | 16 |
17 |
18 | 19 |
20 |
21 | 22 | 24 | 26 |
27 |
29 | 31 |
32 |
33 | 34 |
35 | 36 | 39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/SettingsHooks.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | 20 | import common._ 21 | 22 | import gnieh.sohva.control.entities.EntityManager 23 | 24 | import org.osgi.service.log.LogService 25 | 26 | import com.typesafe.config.Config 27 | 28 | import java.util.concurrent.TimeUnit 29 | 30 | /** This hooks creates the compiler settings when a paper is created 31 | * 32 | * @author Lucas Satabin 33 | */ 34 | class CreateSettingsHook(config: Config, logger: Logger) extends PaperCreated { 35 | 36 | val couchConfig = new CouchConfiguration(config) 37 | 38 | def defaultSettings(paperId: String): CompilerSettings = 39 | CompilerSettings( 40 | s"$paperId:compiler", 41 | config.getString("compiler.default"), 42 | config.getBoolean("compiler.synctex"), 43 | config.getDuration("compiler.timeout", TimeUnit.SECONDS).toInt, 44 | config.getDuration("compiler.interval", TimeUnit.SECONDS).toInt 45 | ) 46 | 47 | def afterCreate(paperId: String, manager: EntityManager): Unit = { 48 | // after creation of a paper, save default settings 49 | manager.saveComponent(paperId, defaultSettings(paperId)) recover { 50 | case t => 51 | logger.log(LogService.LOG_ERROR, s"Unable to create paper settings for paper $paperId", t) 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-kuroir.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/kuroir",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-kuroir",t.cssText=".ace-kuroir .ace_gutter {background: #e8e8e8;color: #333;}.ace-kuroir .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-kuroir {background-color: #E8E9E8;color: #363636;}.ace-kuroir .ace_cursor {color: #202020;}.ace-kuroir .ace_marker-layer .ace_selection {background: rgba(245, 170, 0, 0.57);}.ace-kuroir.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #E8E9E8;}.ace-kuroir .ace_marker-layer .ace_step {background: rgb(198, 219, 174);}.ace-kuroir .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(0, 0, 0, 0.29);}.ace-kuroir .ace_marker-layer .ace_active-line {background: rgba(203, 220, 47, 0.22);}.ace-kuroir .ace_gutter-active-line {background-color: rgba(203, 220, 47, 0.22);}.ace-kuroir .ace_marker-layer .ace_selected-word {border: 1px solid rgba(245, 170, 0, 0.57);}.ace-kuroir .ace_invisible {color: #BFBFBF}.ace-kuroir .ace_fold {border-color: #363636;}.ace-kuroir .ace_constant{color:#CD6839;}.ace-kuroir .ace_constant.ace_numeric{color:#9A5925;}.ace-kuroir .ace_support{color:#104E8B;}.ace-kuroir .ace_support.ace_function{color:#005273;}.ace-kuroir .ace_support.ace_constant{color:#CF6A4C;}.ace-kuroir .ace_storage{color:#A52A2A;}.ace-kuroir .ace_invalid.ace_illegal{color:#FD1224;background-color:rgba(255, 6, 0, 0.15);}.ace-kuroir .ace_invalid.ace_deprecated{text-decoration:underline;font-style:italic;color:#FD1732;background-color:#E8E9E8;}.ace-kuroir .ace_string{color:#639300;}.ace-kuroir .ace_string.ace_regexp{color:#417E00;background-color:#C9D4BE;}.ace-kuroir .ace_comment{color:rgba(148, 148, 148, 0.91);background-color:rgba(220, 220, 220, 0.56);}.ace-kuroir .ace_variable{color:#009ACD;}.ace-kuroir .ace_meta.ace_tag{color:#005273;}.ace-kuroir .ace_markup.ace_heading{color:#B8012D;background-color:rgba(191, 97, 51, 0.051);}.ace-kuroir .ace_markup.ace_list{color:#8F5B26;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/impl/ReCaptchaImpl.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package common 18 | package impl 19 | 20 | import tiscaf._ 21 | 22 | import net.tanesha.recaptcha.{ 23 | ReCaptchaImpl, 24 | ReCaptchaResponse 25 | } 26 | 27 | /** @author Lucas Satabin 28 | * 29 | */ 30 | class ReCaptchaUtilImpl(configuration: BlueConfiguration) extends ReCaptcha { 31 | 32 | val RECAPTCHA_RESPONSE_FIELD = "recaptcha_response_field" 33 | val RECAPTCHA_CHALLENGE_FIELD = "recaptcha_challenge_field" 34 | 35 | /** ReCaptcha is enabled if the private key is configured */ 36 | def enabled_? = 37 | configuration.recaptchaPrivateKey.isDefined 38 | 39 | def verify(talk: HTalk) = if (enabled_?) { 40 | val challenge = talk.req.param(RECAPTCHA_CHALLENGE_FIELD) 41 | val response = talk.req.param(RECAPTCHA_RESPONSE_FIELD) 42 | 43 | (challenge, response) match { 44 | case (Some(c), Some(r)) => 45 | val reCaptcha = new ReCaptchaImpl 46 | 47 | // no exception will be thrown because with checked that the private key 48 | // is defined 49 | reCaptcha.setPrivateKey(configuration.recaptchaPrivateKey.get) 50 | 51 | val reCaptchaResponse = 52 | reCaptcha.checkAnswer(talk.req.remoteIp, c, r) 53 | 54 | reCaptchaResponse.isValid 55 | case _ => false 56 | } 57 | } else { 58 | true 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /blue-web/src/main/scala/gnieh/blue/web/ConfigLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package web 18 | 19 | import tiscaf._ 20 | import let._ 21 | 22 | import org.osgi.framework.BundleContext 23 | 24 | import com.typesafe.config.Config 25 | 26 | import http.BlueLet 27 | 28 | import scala.util.Try 29 | 30 | /** Returns the base configuration data needed by the client. 31 | * 32 | * @author Lucas Satabin 33 | */ 34 | class ConfigLet(context: BundleContext, config: Config) extends HSimpleLet { 35 | 36 | import BlueLet._ 37 | 38 | def act(talk: HTalk): Unit = { 39 | val recaptcha = Try(config.getString("recaptcha.public-key")).toOption 40 | val compilationType = Try(config.getString("compiler.compilation-type")).toOption 41 | 42 | val issuesURL = config.getString("blue.client.issues-url") match { 43 | case "" => None 44 | case s => Some(s) 45 | } 46 | 47 | val cloneURL = config.getString("blue.client.clone-url") match { 48 | case "" => None 49 | case s => Some(s) 50 | } 51 | 52 | val requireValidation = 53 | config.getString("blue.registration-confirmation") == "email-confirmation" 54 | 55 | talk.writeJson( 56 | AppConfig( 57 | config.getString("blue.api.path-prefix"), 58 | requireValidation, 59 | recaptcha, 60 | compilationType, 61 | issuesURL, 62 | cloneURL) 63 | ) 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-clouds.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/clouds",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-clouds",t.cssText='.ace-clouds .ace_gutter {background: #ebebeb;color: #333}.ace-clouds .ace_print-margin {width: 1px;background: #e8e8e8}.ace-clouds {background-color: #FFFFFF;color: #000000}.ace-clouds .ace_cursor {color: #000000}.ace-clouds .ace_marker-layer .ace_selection {background: #BDD5FC}.ace-clouds.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FFFFFF;}.ace-clouds .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-clouds .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #BFBFBF}.ace-clouds .ace_marker-layer .ace_active-line {background: #FFFBD1}.ace-clouds .ace_gutter-active-line {background-color : #dcdcdc}.ace-clouds .ace_marker-layer .ace_selected-word {border: 1px solid #BDD5FC}.ace-clouds .ace_invisible {color: #BFBFBF}.ace-clouds .ace_keyword,.ace-clouds .ace_meta,.ace-clouds .ace_support.ace_constant.ace_property-value {color: #AF956F}.ace-clouds .ace_keyword.ace_operator {color: #484848}.ace-clouds .ace_keyword.ace_other.ace_unit {color: #96DC5F}.ace-clouds .ace_constant.ace_language {color: #39946A}.ace-clouds .ace_constant.ace_numeric {color: #46A609}.ace-clouds .ace_constant.ace_character.ace_entity {color: #BF78CC}.ace-clouds .ace_invalid {background-color: #FF002A}.ace-clouds .ace_fold {background-color: #AF956F;border-color: #000000}.ace-clouds .ace_storage,.ace-clouds .ace_support.ace_class,.ace-clouds .ace_support.ace_function,.ace-clouds .ace_support.ace_other,.ace-clouds .ace_support.ace_type {color: #C52727}.ace-clouds .ace_string {color: #5D90CD}.ace-clouds .ace_comment {color: #BCC8BA}.ace-clouds .ace_entity.ace_name.ace_tag,.ace-clouds .ace_entity.ace_other.ace_attribute-name {color: #606060}.ace-clouds .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-compile/src/main/scala/gnieh/blue/compile/impl/let/CleanLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package compile 18 | package impl 19 | 20 | import http._ 21 | import common._ 22 | import permission._ 23 | 24 | import tiscaf._ 25 | 26 | import scala.util.Try 27 | 28 | import com.typesafe.config.Config 29 | 30 | import gnieh.sohva.control.CouchClient 31 | 32 | /** Cleans the working directory by deleting all files generated by the latex compiler 33 | * and/or bibtex. 34 | * 35 | * @author Lucas Satabin 36 | */ 37 | class CleanLet(paperId: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncPermissionLet(paperId, config, logger) { 38 | 39 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Any] = permissions match { 40 | case Edit() => 41 | 42 | import FileUtils._ 43 | 44 | Try { 45 | // delete all temporary files 46 | val paperDir = configuration.buildDir(paperId) 47 | val ok = paperDir.filter(_.isTeXTemporary).foldLeft(true) { (acc, tmp) => 48 | tmp.delete && acc 49 | } 50 | // and send answer back 51 | talk.writeJson(ok) 52 | } 53 | 54 | case _ => 55 | Try( 56 | talk 57 | .setStatus(HStatus.Forbidden) 58 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to clean compilation results"))) 59 | 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-eclipse.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/eclipse",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssText='.ace-eclipse .ace_gutter {background: #ebebeb;border-right: 1px solid rgb(159, 159, 159);color: rgb(136, 136, 136);}.ace-eclipse .ace_print-margin {width: 1px;background: #ebebeb;}.ace-eclipse {background-color: #FFFFFF;color: black;}.ace-eclipse .ace_fold {background-color: rgb(60, 76, 114);}.ace-eclipse .ace_cursor {color: black;}.ace-eclipse .ace_storage,.ace-eclipse .ace_keyword,.ace-eclipse .ace_variable {color: rgb(127, 0, 85);}.ace-eclipse .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-eclipse .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-eclipse .ace_function {color: rgb(60, 76, 114);}.ace-eclipse .ace_string {color: rgb(42, 0, 255);}.ace-eclipse .ace_comment {color: rgb(113, 150, 130);}.ace-eclipse .ace_comment.ace_doc {color: rgb(63, 95, 191);}.ace-eclipse .ace_comment.ace_doc.ace_tag {color: rgb(127, 159, 191);}.ace-eclipse .ace_constant.ace_numeric {color: darkblue;}.ace-eclipse .ace_tag {color: rgb(25, 118, 116);}.ace-eclipse .ace_type {color: rgb(127, 0, 127);}.ace-eclipse .ace_xml-pe {color: rgb(104, 104, 91);}.ace-eclipse .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-eclipse .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-eclipse .ace_meta.ace_tag {color:rgb(25, 118, 116);}.ace-eclipse .ace_invisible {color: #ddd;}.ace-eclipse .ace_entity.ace_other.ace_attribute-name {color:rgb(127, 0, 127);}.ace-eclipse .ace_marker-layer .ace_step {background: rgb(255, 255, 0);}.ace-eclipse .ace_active-line {background: rgb(232, 242, 254);}.ace-eclipse .ace_gutter-active-line {background-color : #DADADA;}.ace-eclipse .ace_marker-layer .ace_selected-word {border: 1px solid rgb(181, 213, 255);}.ace-eclipse .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}',t.cssClass="ace-eclipse";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/PartPaperLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import http._ 22 | import common._ 23 | import permission._ 24 | 25 | import com.typesafe.config.Config 26 | 27 | import akka.actor.ActorSystem 28 | 29 | import tiscaf._ 30 | 31 | import scala.util.Try 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Notify the system that the user left a given paper 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class PartPaperLet( 40 | paperId: String, 41 | peerId: String, 42 | system: ActorSystem, 43 | val couch: CouchClient, 44 | config: Config, 45 | logger: Logger) extends SyncPermissionLet(paperId, config, logger) { 46 | 47 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = Try { 48 | permissions match { 49 | case Edit() | Read() => 50 | // remove this peer from the current session 51 | for(peers <- SessionKeys.get[Set[String]](SessionKeys.Peers)) 52 | talk.ses(SessionKeys.Peers) = peers - peerId 53 | 54 | system.eventStream.publish(Part(peerId, Some(paperId))) 55 | talk.writeJson(true) 56 | case _ => 57 | talk 58 | .setStatus(HStatus.Unauthorized) 59 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to leave the paper")) 60 | } 61 | } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /blue-mobwrite/src/main/scala/gnieh/blue/mobwrite/MobwriteServer.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package mobwrite 18 | 19 | import resource._ 20 | import common.{SynchroServer, SynchroFailureException} 21 | 22 | import java.net.Socket 23 | import java.io.BufferedInputStream 24 | 25 | import scala.io.Source 26 | import scala.util.{Try, Failure, Success} 27 | 28 | import com.typesafe.config.Config 29 | 30 | /** A synchronization server that simply delegates the work 31 | * to a standalone mobwrite daemon 32 | * 33 | * @author Lucas Satabin 34 | */ 35 | class MobwriteServer(configuration: Config) extends SynchroServer { 36 | 37 | val url = configuration.getString("mobwrite.url") 38 | val port = configuration.getInt("mobwrite.port") 39 | 40 | def session(data: String): Try[String] = { 41 | (for(socket <- managed(new Socket(url, port))) yield { 42 | // Write data to daemon 43 | val outputStream = socket.getOutputStream 44 | outputStream.write(data.getBytes) 45 | outputStream.flush 46 | // Read the response from python and copy it to out 47 | val source = Source.fromInputStream(socket.getInputStream) 48 | 49 | source.foldLeft(new StringBuilder) { (res, current) => 50 | res += current 51 | }.toString 52 | }).opt.fold[Try[String]](Failure(new SynchroFailureException("Error with legacy mobwrite server")))(Success(_)) 53 | } 54 | 55 | def persist(paperId: String): Unit = { 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/GetPaperPermissionsLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import http.{ 22 | SyncPermissionLet, 23 | ErrorResponse 24 | } 25 | 26 | import common.{ 27 | Logger, 28 | UserInfo 29 | } 30 | 31 | import permission._ 32 | 33 | import couch.{ 34 | Paper, 35 | PaperPhase 36 | } 37 | 38 | import com.typesafe.config.Config 39 | 40 | import tiscaf.{ 41 | HTalk, 42 | HStatus 43 | } 44 | 45 | import scala.io.Source 46 | 47 | import scala.util.Try 48 | 49 | import gnieh.sohva.control.CouchClient 50 | 51 | /** Returns the paper roles 52 | * 53 | * @author Lucas Satabin 54 | */ 55 | class GetPaperPermissionsLet(paperid: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncPermissionLet(paperid, config, logger) { 56 | 57 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = permissions match { 58 | case Configure() => 59 | val manager = entityManager("blue_papers") 60 | for(Some(phase @ PaperPhase(_, _, permissions, _)) <- manager.getComponent[PaperPhase](paperid)) 61 | yield talk.writeJson(permissions, phase._rev.get) 62 | 63 | case _ => 64 | Try( 65 | talk 66 | .setStatus(HStatus.Forbidden) 67 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to see paper permissions"))) 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /project/sed.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2004 The Apache Software Foundation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package blue 19 | 20 | import java.io.{ 21 | File, 22 | FileInputStream, 23 | FileOutputStream, 24 | IOException, 25 | PrintStream 26 | } 27 | import java.nio.ByteBuffer 28 | import java.nio.channels.FileChannel 29 | import java.nio.charset.{ 30 | Charset, 31 | CharsetDecoder 32 | } 33 | 34 | object sed { 35 | 36 | def replaceAll(file: File, substitue: String, substituteReplacement: String): Unit = { 37 | 38 | val pattern = substitue.r 39 | 40 | // Open the file and then get a channel from the stream 41 | val fis = new FileInputStream(file) 42 | val fc = fis.getChannel 43 | 44 | val outString = try { 45 | // Get the file's size and then map it into memory 46 | val sz = fc.size 47 | val bb = ByteBuffer.allocate(sz.asInstanceOf[Int]) 48 | fc.read(bb) 49 | bb.rewind() 50 | 51 | val charset = Charset.forName("UTF-8") 52 | val decoder = charset.newDecoder 53 | val cb = decoder.decode(bb) 54 | 55 | pattern.replaceAllIn(cb, substituteReplacement) 56 | } finally { 57 | fc.close 58 | fis.close 59 | } 60 | 61 | val fos = new FileOutputStream(file.getAbsolutePath) 62 | val ps =new PrintStream(fos) 63 | try { 64 | ps.print(outString) 65 | } finally { 66 | ps.close() 67 | fos.close() 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-github.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/github",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-github",t.cssText='.ace-github .ace_gutter {background: #e8e8e8;color: #AAA;}.ace-github {background: #fff;color: #000;}.ace-github .ace_keyword {font-weight: bold;}.ace-github .ace_string {color: #D14;}.ace-github .ace_variable.ace_class {color: teal;}.ace-github .ace_constant.ace_numeric {color: #099;}.ace-github .ace_constant.ace_buildin {color: #0086B3;}.ace-github .ace_support.ace_function {color: #0086B3;}.ace-github .ace_comment {color: #998;font-style: italic;}.ace-github .ace_variable.ace_language {color: #0086B3;}.ace-github .ace_paren {font-weight: bold;}.ace-github .ace_boolean {font-weight: bold;}.ace-github .ace_string.ace_regexp {color: #009926;font-weight: normal;}.ace-github .ace_variable.ace_instance {color: teal;}.ace-github .ace_constant.ace_language {font-weight: bold;}.ace-github .ace_cursor {color: black;}.ace-github.ace_focus .ace_marker-layer .ace_active-line {background: rgb(255, 255, 204);}.ace-github .ace_marker-layer .ace_active-line {background: rgb(245, 245, 245);}.ace-github .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-github.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-github.ace_nobold .ace_line > span {font-weight: normal !important;}.ace-github .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-github .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-github .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-github .ace_gutter-active-line {background-color : rgba(0, 0, 0, 0.07);}.ace-github .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-github .ace_invisible {color: #BFBFBF}.ace-github .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-github .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/paper/NonSynchronizedResourcesLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package paper 20 | 21 | import com.typesafe.config.Config 22 | 23 | import tiscaf._ 24 | 25 | import http._ 26 | import common._ 27 | import permission._ 28 | 29 | import scala.io.Source 30 | 31 | import scala.util.Try 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Gives access to the non-synchronized resource list for the given paper. 36 | * 37 | * @author Lucas Satabin 38 | */ 39 | class NonSynchronizedResourcesLet(paperId: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncPermissionLet(paperId, config, logger) { 40 | 41 | def permissionAct(user: Option[UserInfo], role: Role, permissions: Set[Permission])(implicit talk: HTalk): Try[Unit] = Try(permissions match { 42 | case Edit() => 43 | import FileUtils._ 44 | val files = 45 | configuration 46 | .paperDir(paperId) 47 | .filter(f => 48 | !f.extension.matches(synchronizedExt) 49 | && !f.extension.matches(generatedExt) 50 | && !f.isHidden 51 | && !f.isDirectory 52 | ) 53 | .map(_.getName) 54 | talk.writeJson(files) 55 | case _ => 56 | talk 57 | .setStatus(HStatus.Forbidden) 58 | .writeJson(ErrorResponse("no_sufficient_rights", "You have no permission to see the list of non synchronized resources")) 59 | }) 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/session/LoginLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package session 20 | 21 | import com.typesafe.config.Config 22 | 23 | import http._ 24 | import common._ 25 | 26 | import tiscaf._ 27 | 28 | import scala.util.{ 29 | Try, 30 | Success 31 | } 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | /** Log the user in. 36 | * It delegates to the CouchDB login system and keeps track of the CouchDB cookie 37 | * 38 | * @author Lucas Satabin 39 | */ 40 | class LoginLet(val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) { 41 | 42 | def act(talk: HTalk): Try[Any] = { 43 | implicit val t = talk 44 | (talk.req.param("username"), talk.req.param("password")) match { 45 | case (Some(username), Some(password)) => 46 | couchSession.login(username, password) map { 47 | case true => 48 | // save the current user name in the session 49 | talk.ses(SessionKeys.Username) = username 50 | talk.writeJson(true) 51 | case false => 52 | talk 53 | .setStatus(HStatus.Unauthorized) 54 | .writeJson(ErrorResponse("unable_to_login", "Wrong username and/or password")) 55 | } 56 | case (_, _) => 57 | Success(talk 58 | .setStatus(HStatus.BadRequest) 59 | .writeJson(ErrorResponse("unable_to_login", "Missing login information"))) 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/user/GetUserPapersLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package user 20 | 21 | import http._ 22 | import couch.{ 23 | User, 24 | UserRole, 25 | Paper 26 | } 27 | import common._ 28 | 29 | import com.typesafe.config.Config 30 | 31 | import tiscaf._ 32 | 33 | import gnieh.sohva.control.CouchClient 34 | 35 | import scala.io.Source 36 | 37 | import scala.util.Try 38 | 39 | /** Returns the list of paper a user is involved in, together with his role for this paper. 40 | * 41 | * @author Lucas Satabin 42 | */ 43 | class GetUserPapersLet(username: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 44 | 45 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Unit] = 46 | // only authenticated users may see other people information 47 | view(blue_papers, "papers", "for").query[String, UserRole, Any](key = Some(username)) flatMap { res => 48 | val roles = res.values 49 | val result = 50 | (for { 51 | (_, UserRole(id, role)) <- roles 52 | } yield (id, role)).toList 53 | 54 | for(papers <- database(blue_papers).getDocsById[Paper](result.map(id => s"${id._1}:core"))) 55 | yield talk.writeJson((result zip papers) map { 56 | case ((id, role), Paper(_, name, created)) => Map("id" -> id, "role" -> role, "name" -> name, "creation_date" -> created) 57 | }) 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-vibrant_ink.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/vibrant_ink",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-vibrant-ink",t.cssText=".ace-vibrant-ink .ace_gutter {background: #1a1a1a;color: #BEBEBE}.ace-vibrant-ink .ace_print-margin {width: 1px;background: #1a1a1a}.ace-vibrant-ink {background-color: #0F0F0F;color: #FFFFFF}.ace-vibrant-ink .ace_cursor {color: #FFFFFF}.ace-vibrant-ink .ace_marker-layer .ace_selection {background: #6699CC}.ace-vibrant-ink.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #0F0F0F;}.ace-vibrant-ink .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-vibrant-ink .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-vibrant-ink .ace_marker-layer .ace_active-line {background: #333333}.ace-vibrant-ink .ace_gutter-active-line {background-color: #333333}.ace-vibrant-ink .ace_marker-layer .ace_selected-word {border: 1px solid #6699CC}.ace-vibrant-ink .ace_invisible {color: #404040}.ace-vibrant-ink .ace_keyword,.ace-vibrant-ink .ace_meta {color: #FF6600}.ace-vibrant-ink .ace_constant,.ace-vibrant-ink .ace_constant.ace_character,.ace-vibrant-ink .ace_constant.ace_character.ace_escape,.ace-vibrant-ink .ace_constant.ace_other {color: #339999}.ace-vibrant-ink .ace_constant.ace_numeric {color: #99CC99}.ace-vibrant-ink .ace_invalid,.ace-vibrant-ink .ace_invalid.ace_deprecated {color: #CCFF33;background-color: #000000}.ace-vibrant-ink .ace_fold {background-color: #FFCC00;border-color: #FFFFFF}.ace-vibrant-ink .ace_entity.ace_name.ace_function,.ace-vibrant-ink .ace_support.ace_function,.ace-vibrant-ink .ace_variable {color: #FFCC00}.ace-vibrant-ink .ace_variable.ace_parameter {font-style: italic}.ace-vibrant-ink .ace_string {color: #66FF00}.ace-vibrant-ink .ace_string.ace_regexp {color: #44B4CC}.ace-vibrant-ink .ace_comment {color: #9933CC}.ace-vibrant-ink .ace_entity.ace_other.ace_attribute-name {font-style: italic;color: #99CC99}.ace-vibrant-ink .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYNDTc/oPAALPAZ7hxlbYAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/user/GetUserPermissionsLet.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | package user 20 | 21 | import http._ 22 | import couch.UserPermissions 23 | 24 | import common._ 25 | 26 | import com.typesafe.config.Config 27 | 28 | import tiscaf._ 29 | 30 | import gnieh.sohva.control.CouchClient 31 | 32 | import scala.io.Source 33 | 34 | import scala.util.Try 35 | 36 | /** Returns the list of permissions a user defined. 37 | * 38 | * @author Lucas Satabin 39 | */ 40 | class GetUserPermissionsLet(username: String, val couch: CouchClient, config: Config, logger: Logger) extends SyncBlueLet(config, logger) with SyncAuthenticatedLet { 41 | 42 | def authenticatedAct(user: UserInfo)(implicit talk: HTalk): Try[Any] = { 43 | val namesOnly = talk.req.param("names_only").map(_ == "true").getOrElse(false) 44 | // built-in permissions 45 | val builtin = config.getBuiltInPermissions 46 | val manager = entityManager("blue_users") 47 | for(perms <- manager.getComponent[UserPermissions](f"org.couchdb.user:${user.name}")) 48 | yield perms match { 49 | case Some(p @ UserPermissions(_, perms)) => 50 | if(namesOnly) 51 | talk.writeJson(builtin.keys ++ perms.keys, p._rev.get) 52 | else 53 | talk.writeJson(builtin ++ perms, p._rev.get) 54 | case None => 55 | if(namesOnly) 56 | talk.writeJson(builtin.keys) 57 | else 58 | talk.writeJson(builtin) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-dawn.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/dawn",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-dawn",t.cssText=".ace-dawn .ace_gutter {background: #ebebeb;color: #333}.ace-dawn .ace_print-margin {width: 1px;background: #e8e8e8}.ace-dawn {background-color: #F9F9F9;color: #080808}.ace-dawn .ace_cursor {color: #000000}.ace-dawn .ace_marker-layer .ace_selection {background: rgba(39, 95, 255, 0.30)}.ace-dawn.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #F9F9F9;}.ace-dawn .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-dawn .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(75, 75, 126, 0.50)}.ace-dawn .ace_marker-layer .ace_active-line {background: rgba(36, 99, 180, 0.12)}.ace-dawn .ace_gutter-active-line {background-color : #dcdcdc}.ace-dawn .ace_marker-layer .ace_selected-word {border: 1px solid rgba(39, 95, 255, 0.30)}.ace-dawn .ace_invisible {color: rgba(75, 75, 126, 0.50)}.ace-dawn .ace_keyword,.ace-dawn .ace_meta {color: #794938}.ace-dawn .ace_constant,.ace-dawn .ace_constant.ace_character,.ace-dawn .ace_constant.ace_character.ace_escape,.ace-dawn .ace_constant.ace_other {color: #811F24}.ace-dawn .ace_invalid.ace_illegal {text-decoration: underline;font-style: italic;color: #F8F8F8;background-color: #B52A1D}.ace-dawn .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #B52A1D}.ace-dawn .ace_support {color: #691C97}.ace-dawn .ace_support.ace_constant {color: #B4371F}.ace-dawn .ace_fold {background-color: #794938;border-color: #080808}.ace-dawn .ace_list,.ace-dawn .ace_markup.ace_list,.ace-dawn .ace_support.ace_function {color: #693A17}.ace-dawn .ace_storage {font-style: italic;color: #A71D5D}.ace-dawn .ace_string {color: #0B6125}.ace-dawn .ace_string.ace_regexp {color: #CF5628}.ace-dawn .ace_comment {font-style: italic;color: #5A525F}.ace-dawn .ace_heading,.ace-dawn .ace_markup.ace_heading {color: #19356D}.ace-dawn .ace_variable {color: #234A97}.ace-dawn .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-merbivore.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/merbivore",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-merbivore",t.cssText=".ace-merbivore .ace_gutter {background: #202020;color: #E6E1DC}.ace-merbivore .ace_print-margin {width: 1px;background: #555651}.ace-merbivore {background-color: #161616;color: #E6E1DC}.ace-merbivore .ace_cursor {color: #FFFFFF}.ace-merbivore .ace_marker-layer .ace_selection {background: #454545}.ace-merbivore.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #161616;}.ace-merbivore .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-merbivore .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-merbivore .ace_marker-layer .ace_active-line {background: #333435}.ace-merbivore .ace_gutter-active-line {background-color: #333435}.ace-merbivore .ace_marker-layer .ace_selected-word {border: 1px solid #454545}.ace-merbivore .ace_invisible {color: #404040}.ace-merbivore .ace_entity.ace_name.ace_tag,.ace-merbivore .ace_keyword,.ace-merbivore .ace_meta,.ace-merbivore .ace_meta.ace_tag,.ace-merbivore .ace_storage,.ace-merbivore .ace_support.ace_function {color: #FC6F09}.ace-merbivore .ace_constant,.ace-merbivore .ace_constant.ace_character,.ace-merbivore .ace_constant.ace_character.ace_escape,.ace-merbivore .ace_constant.ace_other,.ace-merbivore .ace_support.ace_type {color: #1EDAFB}.ace-merbivore .ace_constant.ace_character.ace_escape {color: #519F50}.ace-merbivore .ace_constant.ace_language {color: #FDC251}.ace-merbivore .ace_constant.ace_library,.ace-merbivore .ace_string,.ace-merbivore .ace_support.ace_constant {color: #8DFF0A}.ace-merbivore .ace_constant.ace_numeric {color: #58C554}.ace-merbivore .ace_invalid {color: #FFFFFF;background-color: #990000}.ace-merbivore .ace_fold {background-color: #FC6F09;border-color: #E6E1DC}.ace-merbivore .ace_comment {font-style: italic;color: #AD2EA4}.ace-merbivore .ace_entity.ace_other.ace_attribute-name {color: #FFFF89}.ace-merbivore .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQFxf3ZXB1df0PAAdsAmERTkEHAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/js/user/services/SessionService.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | angular.module("bluelatex.User.Services.Session", ["ngResource"]) 18 | .factory("SessionService", [ 19 | '$resource', 20 | '$http', 21 | 'config', 22 | function ($resource, 23 | $http, 24 | config) { 25 | 26 | var api_prefix = config.api_prefix; 27 | 28 | var session = $resource(api_prefix + "/session", null, { 29 | "login": { 30 | method: "POST", 31 | headers: { 32 | 'Content-Type': 'application/x-www-form-urlencoded' 33 | }, 34 | transformResponse: [ 35 | 36 | function (data, headersGetter) { 37 | if (data == 'true') return { 38 | response: JSON.parse(data) 39 | }; 40 | return data; 41 | } 42 | ].concat($http.defaults.transformResponse) 43 | }, 44 | "get": { 45 | method: "GET" 46 | }, 47 | "logout": { 48 | 'method': 'DELETE' 49 | } 50 | }); 51 | 52 | return { 53 | login: function (username, password) { 54 | return session.login({}, jsonToPostParameters({ 55 | "username": username, 56 | 'password': password 57 | })).$promise; 58 | }, 59 | logout: function () { 60 | return session.logout().$promise; 61 | }, 62 | getSession: function () { 63 | return session.get().$promise; 64 | }, 65 | }; 66 | } 67 | ]); -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-idle_fingers.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/idle_fingers",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-idle-fingers",t.cssText=".ace-idle-fingers .ace_gutter {background: #3b3b3b;color: rgb(153,153,153)}.ace-idle-fingers .ace_print-margin {width: 1px;background: #3b3b3b}.ace-idle-fingers {background-color: #323232;color: #FFFFFF}.ace-idle-fingers .ace_cursor {color: #91FF00}.ace-idle-fingers .ace_marker-layer .ace_selection {background: rgba(90, 100, 126, 0.88)}.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #323232;}.ace-idle-fingers .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-idle-fingers .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-idle-fingers .ace_marker-layer .ace_active-line {background: #353637}.ace-idle-fingers .ace_gutter-active-line {background-color: #353637}.ace-idle-fingers .ace_marker-layer .ace_selected-word {border: 1px solid rgba(90, 100, 126, 0.88)}.ace-idle-fingers .ace_invisible {color: #404040}.ace-idle-fingers .ace_keyword,.ace-idle-fingers .ace_meta {color: #CC7833}.ace-idle-fingers .ace_constant,.ace-idle-fingers .ace_constant.ace_character,.ace-idle-fingers .ace_constant.ace_character.ace_escape,.ace-idle-fingers .ace_constant.ace_other,.ace-idle-fingers .ace_support.ace_constant {color: #6C99BB}.ace-idle-fingers .ace_invalid {color: #FFFFFF;background-color: #FF0000}.ace-idle-fingers .ace_fold {background-color: #CC7833;border-color: #FFFFFF}.ace-idle-fingers .ace_support.ace_function {color: #B83426}.ace-idle-fingers .ace_variable.ace_parameter {font-style: italic}.ace-idle-fingers .ace_string {color: #A5C261}.ace-idle-fingers .ace_string.ace_regexp {color: #CCCC33}.ace-idle-fingers .ace_comment {font-style: italic;color: #BC9458}.ace-idle-fingers .ace_meta.ace_tag {color: #FFE5BB}.ace-idle-fingers .ace_entity.ace_name {color: #FFC66D}.ace-idle-fingers .ace_collab.ace_user1 {color: #323232;background-color: #FFF980}.ace-idle-fingers .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjLyZYiPj/8PAAreAwAI1+g0AAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/common/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | 18 | import com.typesafe.config.{ 19 | Config, 20 | ConfigValue 21 | } 22 | 23 | import scala.collection.JavaConverters._ 24 | import scala.util.Try 25 | 26 | package object common { 27 | 28 | type Logger = org.osgi.service.log.LogService 29 | 30 | type UserInfo = gnieh.sohva.UserInfo 31 | 32 | implicit class PermissionsConfig(val config: Config) extends AnyVal { 33 | 34 | def getBuiltInPermissions: Map[String, Map[String, Set[String]]] = 35 | if(config.hasPath("blue.permissions")) { 36 | val permissions = config.getObject("blue.permissions") 37 | Try { 38 | for { 39 | (name, _) <- permissions.asScala 40 | } yield (name, toMap(permissions.toConfig().getConfig(name))) 41 | } map (_.toMap) getOrElse(Map()) 42 | } else { 43 | Map() 44 | } 45 | 46 | } 47 | 48 | def toMap(value: Config): Map[String, Set[String]] = 49 | Map( 50 | "author" -> (if(value.hasPath("author")) value.getStringList("author").asScala.toSet else Set()), 51 | "reviewer" -> (if(value.hasPath("reviewer")) value.getStringList("reviewer").asScala.toSet else Set()), 52 | "guest" -> (if(value.hasPath("guest")) value.getStringList("guest").asScala.toSet else Set()), 53 | "other" -> (if(value.hasPath("other")) value.getStringList("other").asScala.toSet else Set()), 54 | "anonymous" -> (if(value.hasPath("anonymous")) value.getStringList("anonymous").asScala.toSet else Set())) 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /changelog/v1.0.x.markdown: -------------------------------------------------------------------------------- 1 | \BlueLaTeX 1.0.x Family 2 | ======================= 3 | 4 | Version 1.0.0 5 | ------------- 6 | 7 | Initial version. 8 | 9 | Version 1.0.1 10 | ------------- 11 | 12 | Mainly bug fixes in the web client, to make it more comfortable to use. 13 | 14 | - Improve messages (issues #138, #134) 15 | - Disallow ":" in username (issue #139) 16 | - Simplify the use of the web client (issue #135, #143, #146) 17 | - Fix other small but annoying bugs 18 | - Fix a lot of typo 19 | 20 | Version 1.0.2 21 | ------------- 22 | 23 | New patch release with some bug fixes and user experience improvements. 24 | 25 | - Fix a regression in paper option (issue #156) 26 | - Make 'clone' and 'report issue' links configurable (issue #161) 27 | - Add an update script (issue #155) 28 | 29 | Version 1.0.3 30 | ------------- 31 | 32 | Patch release to fix some really annoying bugs and a bug regression. 33 | 34 | - Add button to cleanup compilation directory (issue #173) 35 | - Reload pdf file when compilation failed but produced a new pdf file (issue #168) 36 | - Fix regression bug in web client making it impossible to modify user settings (issue #175) 37 | 38 | Version 1.0.4 39 | ------------- 40 | 41 | Patch release mainly to fix a bug in the synchronization protocol on the server side, and improve the user experience on the client side. 42 | 43 | - Fix the guarantee delivery part in case of disconnection or high latency network (issue #188) 44 | - Hold the scroll position when several authors are editing a file concurrently (issue #185) 45 | - Restore cursor position when changing file (issue #181) 46 | - Fix script loading order to avoid display problems on slow networks (issue #189) 47 | - Reenable use of standard key binings in web browser (issue #171) 48 | - Fix PDF rendering on small displays (issue #182) 49 | 50 | Version 1.0.5 51 | ------------- 52 | 53 | Patch release with a major synchronization bug fix and few UI improvements. 54 | 55 | - Fix synchronization bug that may lead to data loss (issue #188) 56 | - Fix cursor appearing in multiple files (issue #196) 57 | - Fix persistent cursor after an author left the paper (issue #195) 58 | - Cleanup error and wraning upon compilation (issue #201) 59 | - Improvements in the UI 60 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-kr_theme.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/kr_theme",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-kr-theme",t.cssText=".ace-kr-theme .ace_gutter {background: #1c1917;color: #FCFFE0}.ace-kr-theme .ace_print-margin {width: 1px;background: #1c1917}.ace-kr-theme {background-color: #0B0A09;color: #FCFFE0}.ace-kr-theme .ace_cursor {color: #FF9900}.ace-kr-theme .ace_marker-layer .ace_selection {background: rgba(170, 0, 255, 0.45)}.ace-kr-theme.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #0B0A09;}.ace-kr-theme .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-kr-theme .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(255, 177, 111, 0.32)}.ace-kr-theme .ace_marker-layer .ace_active-line {background: #38403D}.ace-kr-theme .ace_gutter-active-line {background-color : #38403D}.ace-kr-theme .ace_marker-layer .ace_selected-word {border: 1px solid rgba(170, 0, 255, 0.45)}.ace-kr-theme .ace_invisible {color: rgba(255, 177, 111, 0.32)}.ace-kr-theme .ace_keyword,.ace-kr-theme .ace_meta {color: #949C8B}.ace-kr-theme .ace_constant,.ace-kr-theme .ace_constant.ace_character,.ace-kr-theme .ace_constant.ace_character.ace_escape,.ace-kr-theme .ace_constant.ace_other {color: rgba(210, 117, 24, 0.76)}.ace-kr-theme .ace_invalid {color: #F8F8F8;background-color: #A41300}.ace-kr-theme .ace_support {color: #9FC28A}.ace-kr-theme .ace_support.ace_constant {color: #C27E66}.ace-kr-theme .ace_fold {background-color: #949C8B;border-color: #FCFFE0}.ace-kr-theme .ace_support.ace_function {color: #85873A}.ace-kr-theme .ace_storage {color: #FFEE80}.ace-kr-theme .ace_string {color: rgba(164, 161, 181, 0.8)}.ace-kr-theme .ace_string.ace_regexp {color: rgba(125, 255, 192, 0.65)}.ace-kr-theme .ace_comment {font-style: italic;color: #706D5B}.ace-kr-theme .ace_variable {color: #D1A796}.ace-kr-theme .ace_list,.ace-kr-theme .ace_markup.ace_list {background-color: #0F0040}.ace-kr-theme .ace_variable.ace_language {color: #FF80E1}.ace-kr-theme .ace_meta.ace_tag {color: #BABD9C}.ace-kr-theme .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-sync/src/main/scala/gnieh/blue/sync/impl/SyncDispatcher.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package sync 18 | package impl 19 | 20 | import akka.actor.{ 21 | Actor, 22 | Props 23 | } 24 | import scala.util.{Try, Success, Failure} 25 | import com.typesafe.config.Config 26 | import org.osgi.framework.BundleContext 27 | import org.osgi.service.log.LogService 28 | import name.fraser.neil.plaintext.DiffMatchPatch 29 | 30 | import store.FsStore 31 | import common._ 32 | 33 | /** The synchronization system actor is responsible for managing 34 | * the synchronisation and persistance of papers. 35 | * 36 | * @author Lucas Satabin 37 | */ 38 | class SyncDispatcher(bndContext: BundleContext, config: Config, val logger: LogService) extends ResourceDispatcher { 39 | 40 | private val configuration = new PaperConfiguration(config) 41 | private val dmp = new DiffMatchPatch 42 | private val store = new FsStore 43 | 44 | def props(username: String, paperId: String): Try[Props] = 45 | Try(Props(new SyncActor(configuration, paperId, store, dmp, logger))) 46 | 47 | override def unknownReceiver(paperId: String, msg: Any): Unit = msg match { 48 | case SyncSession(peerId, paperId, commands) => 49 | sender ! akka.actor.Status.Failure(new SynchroFailureException(s"Nobody is connected to paper $paperId")) 50 | 51 | case PersistPaper(promise) => 52 | promise.complete(Failure(new SynchroFailureException(s"Nobody is connected to paper $paperId"))) 53 | 54 | case LastModificationDate(promise) => 55 | promise.complete(Failure(new SynchroFailureException(s"Nobody is connected to paper $paperId"))) 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-solarized_dark.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/solarized_dark",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-solarized-dark",t.cssText=".ace-solarized-dark .ace_gutter {background: #01313f;color: #d0edf7}.ace-solarized-dark .ace_print-margin {width: 1px;background: #33555E}.ace-solarized-dark {background-color: #002B36;color: #93A1A1}.ace-solarized-dark .ace_entity.ace_other.ace_attribute-name,.ace-solarized-dark .ace_storage {color: #93A1A1}.ace-solarized-dark .ace_cursor,.ace-solarized-dark .ace_string.ace_regexp {color: #D30102}.ace-solarized-dark .ace_marker-layer .ace_active-line,.ace-solarized-dark .ace_marker-layer .ace_selection {background: rgba(255, 255, 255, 0.1)}.ace-solarized-dark.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #002B36;}.ace-solarized-dark .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-solarized-dark .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(147, 161, 161, 0.50)}.ace-solarized-dark .ace_gutter-active-line {background-color: #0d3440}.ace-solarized-dark .ace_marker-layer .ace_selected-word {border: 1px solid #073642}.ace-solarized-dark .ace_invisible {color: rgba(147, 161, 161, 0.50)}.ace-solarized-dark .ace_keyword,.ace-solarized-dark .ace_meta,.ace-solarized-dark .ace_support.ace_class,.ace-solarized-dark .ace_support.ace_type {color: #859900}.ace-solarized-dark .ace_constant.ace_character,.ace-solarized-dark .ace_constant.ace_other {color: #CB4B16}.ace-solarized-dark .ace_constant.ace_language {color: #B58900}.ace-solarized-dark .ace_constant.ace_numeric {color: #D33682}.ace-solarized-dark .ace_fold {background-color: #268BD2;border-color: #93A1A1}.ace-solarized-dark .ace_entity.ace_name.ace_function,.ace-solarized-dark .ace_entity.ace_name.ace_tag,.ace-solarized-dark .ace_support.ace_function,.ace-solarized-dark .ace_variable,.ace-solarized-dark .ace_variable.ace_language {color: #268BD2}.ace-solarized-dark .ace_string {color: #2AA198}.ace-solarized-dark .ace_comment {font-style: italic;color: #657B83}.ace-solarized-dark .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNg0Db1ZVCxc/sPAAd4AlUHlLenAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-cobalt.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/cobalt",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-cobalt",t.cssText=".ace-cobalt .ace_gutter {background: #011e3a;color: rgb(128,145,160)}.ace-cobalt .ace_print-margin {width: 1px;background: #555555}.ace-cobalt {background-color: #002240;color: #FFFFFF}.ace-cobalt .ace_cursor {color: #FFFFFF}.ace-cobalt .ace_marker-layer .ace_selection {background: rgba(179, 101, 57, 0.75)}.ace-cobalt.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #002240;}.ace-cobalt .ace_marker-layer .ace_step {background: rgb(127, 111, 19)}.ace-cobalt .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(255, 255, 255, 0.15)}.ace-cobalt .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.35)}.ace-cobalt .ace_gutter-active-line {background-color: rgba(0, 0, 0, 0.35)}.ace-cobalt .ace_marker-layer .ace_selected-word {border: 1px solid rgba(179, 101, 57, 0.75)}.ace-cobalt .ace_invisible {color: rgba(255, 255, 255, 0.15)}.ace-cobalt .ace_keyword,.ace-cobalt .ace_meta {color: #FF9D00}.ace-cobalt .ace_constant,.ace-cobalt .ace_constant.ace_character,.ace-cobalt .ace_constant.ace_character.ace_escape,.ace-cobalt .ace_constant.ace_other {color: #FF628C}.ace-cobalt .ace_invalid {color: #F8F8F8;background-color: #800F00}.ace-cobalt .ace_support {color: #80FFBB}.ace-cobalt .ace_support.ace_constant {color: #EB939A}.ace-cobalt .ace_fold {background-color: #FF9D00;border-color: #FFFFFF}.ace-cobalt .ace_support.ace_function {color: #FFB054}.ace-cobalt .ace_storage {color: #FFEE80}.ace-cobalt .ace_entity {color: #FFDD00}.ace-cobalt .ace_string {color: #3AD900}.ace-cobalt .ace_string.ace_regexp {color: #80FFC2}.ace-cobalt .ace_comment {font-style: italic;color: #0088FF}.ace-cobalt .ace_heading,.ace-cobalt .ace_markup.ace_heading {color: #C8E4FD;background-color: #001221}.ace-cobalt .ace_list,.ace-cobalt .ace_markup.ace_list {background-color: #130D26}.ace-cobalt .ace_variable {color: #CCCCCC}.ace-cobalt .ace_variable.ace_language {color: #FF80E1}.ace-cobalt .ace_meta.ace_tag {color: #9EFFFF}.ace-cobalt .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHCLSvkPAAP3AgSDTRd4AAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-core/src/main/scala/gnieh/blue/core/impl/BlueCoreActivator.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package core 18 | package impl 19 | 20 | import java.io.File 21 | 22 | import org.osgi.framework._ 23 | import org.osgi.service.log.LogService 24 | 25 | import com.typesafe.config._ 26 | 27 | import akka.actor.ActorSystem 28 | 29 | import http.RestApi 30 | import common._ 31 | 32 | import gnieh.sohva.control.CouchClient 33 | 34 | /** The `BlueActivator` starts the \BlueLaTeX core system: 35 | * - the configuration loader 36 | * - the actor system 37 | * 38 | * @author Lucas Satabin 39 | */ 40 | class BlueCoreActivator extends BundleActivator { 41 | 42 | import OsgiUtils._ 43 | 44 | def start(context: BundleContext): Unit = 45 | for { 46 | loader <- context.get[ConfigurationLoader] 47 | logger <- context.get[Logger] 48 | system <- context.get[ActorSystem] 49 | couch <- context.get[CouchClient] 50 | templates <- context.get[Templates] 51 | mailAgent <- context.get[MailAgent] 52 | recaptcha <- context.get[ReCaptcha] 53 | } try { 54 | // load the \BlueLaTeX common configuration 55 | val config = loader.load(context.getBundle) 56 | val configuration = new BlueConfiguration(config) 57 | 58 | // register the core Rest API 59 | context.registerService(classOf[RestApi], new CoreApi(couch, config, system, context, templates, mailAgent, recaptcha, logger), null) 60 | } catch { 61 | case e: Exception => 62 | logger.log(LogService.LOG_ERROR, s"Unable to start the core bundle", e) 63 | throw e 64 | } 65 | 66 | def stop(context: BundleContext): Unit = { 67 | } 68 | 69 | } 70 | 71 | -------------------------------------------------------------------------------- /blue-dist/src/shell/upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this script to upgrade from previously installed \BlueLaTeX instance 4 | 5 | # Where the \BlueLaTeX binaries are installed 6 | INSTALL_DIR=$install_dir 7 | 8 | # Where the \BlueLaTeX configuration files are installed 9 | CONF_DIR=$conf_dir 10 | 11 | # Where the paper data will be stored 12 | DATA_DIR=$data_dir 13 | 14 | if [[ ! -e "$INSTALL_DIR" && ! (-e "$CONF_DIR" && -e "$DATA_DIR") ]] 15 | then 16 | echo "No previous installation can be found. Please consider using 'install.sh' instead" 17 | exit 1 18 | fi 19 | 20 | if [[ -d "$INSTALL_DIR" ]] 21 | then 22 | # If the installation directory already exists, check the diff between the old and new one 23 | diff -r bundle $INSTALL_DIR/bundle > /dev/null 24 | if [[ $? -ne 0 ]] 25 | then 26 | rm $INSTALL_DIR/bundle/*.jar 27 | cp bundle/*.jar $INSTALL_DIR/bundle/ 28 | fi 29 | diff -r bin $INSTALL_DIR/bin > /dev/null 30 | if [[ $? -ne 0 ]] 31 | then 32 | rm $INSTALL_DIR/bin/* 33 | cp bin/* $INSTALL_DIR/bin/ 34 | fi 35 | else 36 | mkdir -p $INSTALL_DIR 37 | cp -r bin bundle $INSTALL_DIR 38 | fi 39 | 40 | diff -r conf $CONF_DIR > configuration.diff 41 | if [[ $? -ne 0 ]] 42 | then 43 | echo "Configuration has changed since last installed version. Check diff in 'configuration.diff' and take appropriate actions to finish upgrade" 44 | else 45 | rm configuration.diff 46 | fi 47 | 48 | # If the data directory already exists, check the diff between the old and new one 49 | diff -r data/classes $DATA_DIR/classes > classes.diff 50 | if [[ $? -ne 0 ]] 51 | then 52 | echo "LaTeX classes have changed since last installed version. Check diff in 'classes.diff' and take appropriate actions to finish upgrade" 53 | else 54 | rm classes.diff 55 | fi 56 | 57 | diff -r data/designs $DATA_DIR/designs > designs.diff 58 | if [[ $? -ne 0 ]] 59 | then 60 | echo "CouchDB design shave changed since last installed version. Check diff in 'designs.diff' and take appropriate actions to finish upgrade" 61 | else 62 | rm designs.diff 63 | fi 64 | 65 | diff -r data/templates $DATA_DIR/templates > templates.diff 66 | if [[ $? -ne 0 ]] 67 | then 68 | echo "Templates have changed since last installed version. Check diff in 'templates.diff' and take appropriate actions to finish upgrade" 69 | else 70 | rm templates.diff 71 | fi 72 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/couch/PaperRole.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package couch 18 | 19 | import gnieh.sohva.IdRev 20 | 21 | import permission._ 22 | import common.{ 23 | UserInfo, 24 | SingletonSet, 25 | EmptySet 26 | } 27 | 28 | /** Role component that can be attached to a paper entity. 29 | * It lists the roles for users and/or groups. 30 | * 31 | * @author Lucas Satabin 32 | */ 33 | case class PaperRole(_id: String, authors: UsersGroups, reviewers: UsersGroups, guests: UsersGroups) extends IdRev { 34 | 35 | def roleOf(user: Option[UserInfo]): Role = user match { 36 | case Some(userCtx) if authors.contains(userCtx) => Author 37 | case Some(userCtx) if reviewers.contains(userCtx) => Reviewer 38 | case Some(userCtx) if guests.contains(userCtx) => Guest 39 | case Some(userCtx) => Other 40 | case None => Anonymous 41 | } 42 | 43 | } 44 | 45 | object SingleAuthor { 46 | def unapply(roles: PaperRole): Option[String] = 47 | roles.authors match { 48 | case UsersGroups(SingletonSet(author), EmptySet()) => Some(author) 49 | case _ => None 50 | } 51 | } 52 | 53 | case class UsersGroups(users: Set[String], groups: Set[String]) { 54 | 55 | /** A user belongs to a role if he is either explicitly listed in the user list 56 | * or if he belongs to a group that is listed in the group list */ 57 | def contains(user: UserInfo): Boolean = 58 | users.contains(user.name) || groups.intersect(user.roles.toSet).nonEmpty 59 | 60 | def -(user: UserInfo): UsersGroups = 61 | this.copy(users - user.name) 62 | 63 | } 64 | -------------------------------------------------------------------------------- /blue-common/src/main/scala/gnieh/blue/http/impl/BlueServer.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the \BlueLaTeX project. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gnieh.blue 17 | package http 18 | package impl 19 | 20 | import tiscaf._ 21 | 22 | import akka.actor.ActorSystem 23 | 24 | import org.osgi.framework.BundleContext 25 | import org.osgi.util.tracker.ServiceTracker 26 | 27 | import com.typesafe.config._ 28 | 29 | import scala.collection.mutable.{ 30 | Map, 31 | ListBuffer 32 | } 33 | 34 | import common._ 35 | 36 | class BlueServer(context: BundleContext, system: ActorSystem, configuration: Config, val logger: Logger) extends HServer with Logging { 37 | 38 | protected val ports = 39 | Set(configuration.getInt("http.port")) 40 | 41 | protected override val bindHost = 42 | configuration.getString("http.host") 43 | 44 | private val extApp = 45 | new ExtensibleApp(configuration, system) 46 | 47 | private var allApps = 48 | Vector[HApp](extApp) 49 | 50 | protected def apps = 51 | allApps 52 | 53 | private val restTracker = 54 | new RestServiceTracker(context, extApp) 55 | 56 | import OsgiUtils._ 57 | 58 | private val appTracker = 59 | context.trackAll[HApp] { 60 | case ServiceAdded(app) => allApps = allApps :+ app 61 | case ServiceRemoved(app) => allApps = allApps.filter(_ ne app) 62 | } 63 | 64 | override protected def maxPostDataLength = 65 | 100000000 66 | 67 | override protected def onStart: Unit = { 68 | // start the application tracker 69 | restTracker.open() 70 | } 71 | 72 | override protected def onStop: Unit = { 73 | // stop the application tracker 74 | restTracker.close() 75 | appTracker.close() 76 | } 77 | 78 | logInfo("blue server started") 79 | 80 | } 81 | 82 | -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-solarized_light.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/solarized_light",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-solarized-light",t.cssText=".ace-solarized-light .ace_gutter {background: #fbf1d3;color: #333}.ace-solarized-light .ace_print-margin {width: 1px;background: #e8e8e8}.ace-solarized-light {background-color: #FDF6E3;color: #586E75}.ace-solarized-light .ace_cursor {color: #000000}.ace-solarized-light .ace_marker-layer .ace_selection {background: rgba(7, 54, 67, 0.09)}.ace-solarized-light.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #FDF6E3;}.ace-solarized-light .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-solarized-light .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_marker-layer .ace_active-line {background: #EEE8D5}.ace-solarized-light .ace_gutter-active-line {background-color : #EDE5C1}.ace-solarized-light .ace_marker-layer .ace_selected-word {border: 1px solid #073642}.ace-solarized-light .ace_invisible {color: rgba(147, 161, 161, 0.50)}.ace-solarized-light .ace_keyword,.ace-solarized-light .ace_meta,.ace-solarized-light .ace_support.ace_class,.ace-solarized-light .ace_support.ace_type {color: #859900}.ace-solarized-light .ace_constant.ace_character,.ace-solarized-light .ace_constant.ace_other {color: #CB4B16}.ace-solarized-light .ace_constant.ace_language {color: #B58900}.ace-solarized-light .ace_constant.ace_numeric {color: #D33682}.ace-solarized-light .ace_fold {background-color: #268BD2;border-color: #586E75}.ace-solarized-light .ace_entity.ace_name.ace_function,.ace-solarized-light .ace_entity.ace_name.ace_tag,.ace-solarized-light .ace_support.ace_function,.ace-solarized-light .ace_variable,.ace-solarized-light .ace_variable.ace_language {color: #268BD2}.ace-solarized-light .ace_storage {color: #073642}.ace-solarized-light .ace_string {color: #2AA198}.ace-solarized-light .ace_string.ace_regexp {color: #D30102}.ace-solarized-light .ace_comment,.ace-solarized-light .ace_entity.ace_other.ace_attribute-name {color: #93A1A1}.ace-solarized-light .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHjy8NJ/AAjgA5fzQUmBAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /blue-web/src/main/resources/webapp/ace/theme-monokai.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-monokai",t.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) --------------------------------------------------------------------------------