summaryrefslogtreecommitdiffstats
path: root/routers/web/user/setting/security_openid.go
diff options
context:
space:
mode:
Diffstat (limited to 'routers/web/user/setting/security_openid.go')
-rw-r--r--routers/web/user/setting/security_openid.go129
1 files changed, 129 insertions, 0 deletions
diff --git a/routers/web/user/setting/security_openid.go b/routers/web/user/setting/security_openid.go
new file mode 100644
index 0000000000..74dba12825
--- /dev/null
+++ b/routers/web/user/setting/security_openid.go
@@ -0,0 +1,129 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/auth/openid"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/forms"
+)
+
+// OpenIDPost response for change user's openid
+func OpenIDPost(ctx *context.Context) {
+ form := web.GetForm(ctx).(*forms.AddOpenIDForm)
+ ctx.Data["Title"] = ctx.Tr("settings")
+ ctx.Data["PageIsSettingsSecurity"] = true
+
+ if ctx.HasError() {
+ loadSecurityData(ctx)
+
+ ctx.HTML(http.StatusOK, tplSettingsSecurity)
+ return
+ }
+
+ // WARNING: specifying a wrong OpenID here could lock
+ // a user out of her account, would be better to
+ // verify/confirm the new OpenID before storing it
+
+ // Also, consider allowing for multiple OpenID URIs
+
+ id, err := openid.Normalize(form.Openid)
+ if err != nil {
+ loadSecurityData(ctx)
+
+ ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
+ return
+ }
+ form.Openid = id
+ log.Trace("Normalized id: " + id)
+
+ oids, err := models.GetUserOpenIDs(ctx.User.ID)
+ if err != nil {
+ ctx.ServerError("GetUserOpenIDs", err)
+ return
+ }
+ ctx.Data["OpenIDs"] = oids
+
+ // Check that the OpenID is not already used
+ for _, obj := range oids {
+ if obj.URI == id {
+ loadSecurityData(ctx)
+
+ ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &form)
+ return
+ }
+ }
+
+ redirectTo := setting.AppURL + "user/settings/security"
+ url, err := openid.RedirectURL(id, redirectTo, setting.AppURL)
+ if err != nil {
+ loadSecurityData(ctx)
+
+ ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
+ return
+ }
+ ctx.Redirect(url)
+}
+
+func settingsOpenIDVerify(ctx *context.Context) {
+ log.Trace("Incoming call to: " + ctx.Req.URL.String())
+
+ fullURL := setting.AppURL + ctx.Req.URL.String()[1:]
+ log.Trace("Full URL: " + fullURL)
+
+ id, err := openid.Verify(fullURL)
+ if err != nil {
+ ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &forms.AddOpenIDForm{
+ Openid: id,
+ })
+ return
+ }
+
+ log.Trace("Verified ID: " + id)
+
+ oid := &models.UserOpenID{UID: ctx.User.ID, URI: id}
+ if err = models.AddUserOpenID(oid); err != nil {
+ if models.IsErrOpenIDAlreadyUsed(err) {
+ ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &forms.AddOpenIDForm{Openid: id})
+ return
+ }
+ ctx.ServerError("AddUserOpenID", err)
+ return
+ }
+ log.Trace("Associated OpenID %s to user %s", id, ctx.User.Name)
+ ctx.Flash.Success(ctx.Tr("settings.add_openid_success"))
+
+ ctx.Redirect(setting.AppSubURL + "/user/settings/security")
+}
+
+// DeleteOpenID response for delete user's openid
+func DeleteOpenID(ctx *context.Context) {
+ if err := models.DeleteUserOpenID(&models.UserOpenID{ID: ctx.QueryInt64("id"), UID: ctx.User.ID}); err != nil {
+ ctx.ServerError("DeleteUserOpenID", err)
+ return
+ }
+ log.Trace("OpenID address deleted: %s", ctx.User.Name)
+
+ ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success"))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": setting.AppSubURL + "/user/settings/security",
+ })
+}
+
+// ToggleOpenIDVisibility response for toggle visibility of user's openid
+func ToggleOpenIDVisibility(ctx *context.Context) {
+ if err := models.ToggleUserOpenIDVisibility(ctx.QueryInt64("id")); err != nil {
+ ctx.ServerError("ToggleUserOpenIDVisibility", err)
+ return
+ }
+
+ ctx.Redirect(setting.AppSubURL + "/user/settings/security")
+}
ef='#n297'>297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
module.exports = function( grunt ) {

"use strict";

var
	// files
	coreFiles = [
		"jquery.ui.core.js",
		"jquery.ui.widget.js",
		"jquery.ui.mouse.js",
		"jquery.ui.draggable.js",
		"jquery.ui.droppable.js",
		"jquery.ui.resizable.js",
		"jquery.ui.selectable.js",
		"jquery.ui.sortable.js",
		"jquery.ui.effect.js"
	],

	uiFiles = coreFiles.map(function( file ) {
		return "ui/" + file;
	}).concat( grunt.file.expandFiles( "ui/*.js" ).filter(function( file ) {
		return coreFiles.indexOf( file.substring(3) ) === -1;
	})),

	allI18nFiles = grunt.file.expandFiles( "ui/i18n/*.js" ),

	cssFiles = [
		"core",
		"accordion",
		"autocomplete",
		"button",
		"datepicker",
		"dialog",
		"menu",
		"progressbar",
		"resizable",
		"selectable",
		"slider",
		"spinner",
		"tabs",
		"tooltip",
		"theme"
	].map(function( component ) {
		return "themes/base/jquery.ui." + component + ".css";
	}),

	// minified files
	minify = {
		"dist/jquery-ui.min.js": [ "<banner:meta.bannerAll>", "dist/jquery-ui.js" ],
		"dist/i18n/jquery-ui-i18n.min.js": [ "<banner:meta.bannerI18n>", "dist/i18n/jquery-ui-i18n.js" ]
	},

	minifyCSS = {
		"dist/jquery-ui.min.css": "dist/jquery-ui.css"
	},

	compareFiles = {
		all: [
			"dist/jquery-ui.js",
			"dist/jquery-ui.min.js"
		]
	};

function mapMinFile( file ) {
	return "dist/" + file.replace( /\.js$/, ".min.js" ).replace( /ui\//, "minified/" );
}

uiFiles.concat( allI18nFiles ).forEach(function( file ) {
	minify[ mapMinFile( file ) ] = [ "<banner>", file ];
});

cssFiles.forEach(function( file ) {
	minifyCSS[ "dist/" + file.replace( /\.css$/, ".min.css" ).replace( /themes\/base\//, "themes/base/minified/" ) ] = [ "<banner>", "<strip_all_banners:" + file + ">" ];
});

uiFiles.forEach(function( file ) {
	compareFiles[ file ] = [ file,  mapMinFile( file ) ];
});

// grunt plugins
grunt.loadNpmTasks( "grunt-css" );
grunt.loadNpmTasks( "grunt-html" );
grunt.loadNpmTasks( "grunt-compare-size" );
grunt.loadNpmTasks( "grunt-junit" );
grunt.loadNpmTasks( "grunt-git-authors" );
// local testswarm and build tasks
grunt.loadTasks( "build/tasks" );

grunt.registerHelper( "strip_all_banners", function( filepath ) {
	return grunt.file.read( filepath ).replace( /^\s*\/\*[\s\S]*?\*\/\s*/g, "" );
});

function stripBanner( files ) {
	return files.map(function( file ) {
		return "<strip_all_banners:" + file + ">";
	});
}

function stripDirectory( file ) {
	// TODO: we're receiving the directive, so we need to strip the trailing >
	// we should be receving a clean path without the directive
	return file.replace( /.+\/(.+?)>?$/, "$1" );
}
// allow access from banner template
global.stripDirectory = stripDirectory;

function createBanner( files ) {
	// strip folders
	var fileNames = files && files.map( stripDirectory );
	return "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " +
		"<%= grunt.template.today('isoDate') %>\n" +
		"<%= pkg.homepage ? '* ' + pkg.homepage + '\n' : '' %>" +
		"* Includes: " + (files ? fileNames.join(", ") : "<%= stripDirectory(grunt.task.current.file.src[1]) %>") + "\n" +
		"* Copyright <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;" +
		" Licensed <%= _.pluck(pkg.licenses, 'type').join(', ') %> */";
}

grunt.initConfig({
	pkg: "<json:package.json>",
	files: {
		dist: "<%= pkg.name %>-<%= pkg.version %>",
		cdn: "<%= pkg.name %>-<%= pkg.version %>-cdn",
		themes: "<%= pkg.name %>-themes-<%= pkg.version %>"
	},
	meta: {
		banner: createBanner(),
		bannerAll: createBanner( uiFiles ),
		bannerI18n: createBanner( allI18nFiles ),
		bannerCSS: createBanner( cssFiles )
	},
	compare_size: compareFiles,
	concat: {
		ui: {
			src: [ "<banner:meta.bannerAll>", stripBanner( uiFiles ) ],
			dest: "dist/jquery-ui.js"
		},
		i18n: {
			src: [ "<banner:meta.bannerI18n>", allI18nFiles ],
			dest: "dist/i18n/jquery-ui-i18n.js"
		},
		css: {
			src: [ "<banner:meta.bannerCSS>", stripBanner( cssFiles ) ],
			dest: "dist/jquery-ui.css"
		}
	},
	min: minify,
	cssmin: minifyCSS,
	htmllint: {
		// ignore files that contain invalid html, used only for ajax content testing
		all: grunt.file.expand( [ "demos/**/*.html", "tests/**/*.html" ] ).filter(function( file ) {
			return !/(?:ajax\/content\d\.html|tabs\/data\/test\.html|tests\/unit\/core\/core\.html)/.test( file );
		})
	},
	copy: {
		dist: {
			src: [
				"AUTHORS.txt",
				"jquery-*.js",
				"MIT-LICENSE.txt",
				"README.md",
				"grunt.js",
				"package.json",
				"*.jquery.json",
				"ui/**/*",
				"ui/.jshintrc",
				"demos/**/*",
				"themes/**/*",
				"external/**/*",
				"tests/**/*"
			],
			renames: {
				"dist/jquery-ui.js": "ui/jquery-ui.js",
				"dist/jquery-ui.min.js": "ui/minified/jquery-ui.min.js",
				"dist/i18n/jquery-ui-i18n.js": "ui/i18n/jquery-ui-i18n.js",
				"dist/i18n/jquery-ui-i18n.min.js": "ui/minified/i18n/jquery-ui-i18n.min.js",
				"dist/jquery-ui.css": "themes/base/jquery-ui.css",
				"dist/jquery-ui.min.css": "themes/base/minified/jquery-ui.min.css"
			},
			dest: "dist/<%= files.dist %>"
		},
		dist_min: {
			src: "dist/minified/**/*",
			strip: /^dist/,
			dest: "dist/<%= files.dist %>/ui"
		},
		dist_css_min: {
			src: "dist/themes/base/minified/*.css",
			strip: /^dist/,
			dest: "dist/<%= files.dist %>"
		},
		dist_units_images: {
			src: "themes/base/images/*",
			strip: /^themes\/base\//,
			dest: "dist/"
		},
		dist_min_images: {
			src: "themes/base/images/*",
			strip: /^themes\/base\//,
			dest: "dist/<%= files.dist %>/themes/base/minified"
		},
		cdn: {
			src: [
				"AUTHORS.txt",
				"MIT-LICENSE.txt",
				"ui/*.js",
				"package.json"
			],
			renames: {
				"dist/jquery-ui.js": "jquery-ui.js",
				"dist/jquery-ui.min.js": "jquery-ui.min.js",
				"dist/i18n/jquery-ui-i18n.js": "i18n/jquery-ui-i18n.js",
				"dist/i18n/jquery-ui-i18n.min.js": "i18n/jquery-ui-i18n.min.js",
				"dist/jquery-ui.css": "themes/base/jquery-ui.css",
				"dist/jquery-ui.min.css": "themes/base/minified/jquery-ui.min.css"
			},
			dest: "dist/<%= files.cdn %>"
		},
		cdn_i18n: {
			src: "ui/i18n/jquery.ui.datepicker-*.js",
			strip: "ui/",
			dest: "dist/<%= files.cdn %>"
		},
		cdn_i18n_min: {
			src: "dist/minified/i18n/jquery.ui.datepicker-*.js",
			strip: "dist/minified",
			dest: "dist/<%= files.cdn %>"
		},
		cdn_min: {
			src: "dist/minified/*.js",
			strip: /^dist\/minified/,
			dest: "dist/<%= files.cdn %>/ui"
		},
		cdn_min_images: {
			src: "themes/base/images/*",
			strip: /^themes\/base\//,
			dest: "dist/<%= files.cdn %>/themes/base/minified"
		},
		cdn_themes: {
			src: "dist/<%= files.themes %>/themes/**/*",
			strip: "dist/<%= files.themes %>",
			dest: "dist/<%= files.cdn %>"
		},
		themes: {
			src: [
				"AUTHORS.txt",
				"MIT-LICENSE.txt",
				"package.json"
			],
			dest: "dist/<%= files.themes %>"
		}
	},
	zip: {
		dist: {
			src: "<%= files.dist %>",
			dest: "<%= files.dist %>.zip"
		},
		cdn: {
			src: "<%= files.cdn %>",
			dest: "<%= files.cdn %>.zip"
		},
		themes: {
			src: "<%= files.themes %>",
			dest: "<%= files.themes %>.zip"
		}
	},
	md5: {
		dist: {
			src: "dist/<%= files.dist %>",
			dest: "dist/<%= files.dist %>/MANIFEST"
		},
		cdn: {
			src: "dist/<%= files.cdn %>",
			dest: "dist/<%= files.cdn %>/MANIFEST"
		},
		themes: {
			src: "dist/<%= files.themes %>",
			dest: "dist/<%= files.themes %>/MANIFEST"
		}
	},
	qunit: {
		files: grunt.file.expandFiles( "tests/unit/**/*.html" ).filter(function( file ) {
			// disabling everything that doesn't (quite) work with PhantomJS for now
			// TODO except for all|index|test, try to include more as we go
			return !( /(all|all-active|index|test|draggable|droppable|selectable|resizable|sortable|dialog|slider|datepicker|tabs|tabs_deprecated|tooltip)\.html$/ ).test( file );
		})
	},
	lint: {
		ui: grunt.file.expandFiles( "ui/*.js" ).filter(function( file ) {
			// TODO remove items from this list once rewritten
			return !( /(mouse|datepicker|draggable|droppable|resizable|selectable|sortable)\.js$/ ).test( file );
		}),
		grunt: [ "grunt.js", "build/**/*.js" ],
		tests: "tests/unit/**/*.js"
	},
	csslint: {
		// nothing: []
		// TODO figure out what to check for, then fix and enable
		base_theme: {
			src: grunt.file.expandFiles( "themes/base/*.css" ).filter(function( file ) {
				// TODO remove items from this list once rewritten
				return !( /(button|datepicker|core|dialog|theme)\.css$/ ).test( file );
			}),
			// TODO consider reenabling some of these rules
			rules: {
				"import": false,
				"important": false,
				"outline-none": false,
				// especially this one
				"overqualified-elements": false,
				"compatible-vendor-prefixes": false
			}
		}
	},
	jshint: (function() {
		function parserc( path ) {
			var rc = grunt.file.readJSON( (path || "") + ".jshintrc" ),
				settings = {
					options: rc,
					globals: {}
				};

			(rc.predef || []).forEach(function( prop ) {
				settings.globals[ prop ] = true;
			});
			delete rc.predef;

			return settings;
		}

		return {
			grunt: parserc(),
			ui: parserc( "ui/" ),
			// TODO: `evil: true` is only for document.write() https://github.com/jshint/jshint/issues/519
			// TODO: don't create so many globals in tests
			tests: parserc( "tests/" )
		};
	})()
});

grunt.registerTask( "default", "lint csslint htmllint qunit" );
grunt.registerTask( "sizer", "concat:ui min:dist/jquery-ui.min.js compare_size:all" );
grunt.registerTask( "sizer_all", "concat:ui min compare_size" );
grunt.registerTask( "build", "concat min cssmin copy:dist_units_images" );
grunt.registerTask( "release", "clean build copy:dist copy:dist_min copy:dist_min_images copy:dist_css_min md5:dist zip:dist" );
grunt.registerTask( "release_themes", "release generate_themes copy:themes md5:themes zip:themes" );
grunt.registerTask( "release_cdn", "release_themes copy:cdn copy:cdn_min copy:cdn_i18n copy:cdn_i18n_min copy:cdn_min_images copy:cdn_themes md5:cdn zip:cdn" );

};