diff --git a/dash/admin/forms.py b/dash/admin/forms.py index 341d478..d0d78e2 100644 --- a/dash/admin/forms.py +++ b/dash/admin/forms.py @@ -3,7 +3,7 @@ from flask import flash from wtforms import StringField, PasswordField, BooleanField, SubmitField, \ ValidationError, SelectField from wtforms.validators import Required, Length, Email, Regexp, EqualTo -from ..models import User, Role +from ..models import User, Role, Provider class EditUserAdminForm(Form): email = StringField('Email', validators=[Required(), Length(1, 128), @@ -58,4 +58,53 @@ class CreateUserAdminForm(Form): class DeleteUserAdminForm(Form): confirm = BooleanField('Confirmed', validators=[Required(message='You must confirm to delete.')]) - \ No newline at end of file + +class CreateUserProviderAdminForm(Form): + provider = SelectField('Provider', coerce=int) + + def __init__(self, user, *args, **kwargs): + super(CreateUserProviderAdminForm, self).__init__(*args, **kwargs) + self.provider.choices = [(provider.id, provider.name) + for provider in Provider.query.order_by(Provider.name).all()] + +class CreateProviderAdminForm(Form): + provider = SelectField('Provider', validators=[Required()], + choices=[('openstack', 'OpenStack'), ('other', 'Other')]) + name = StringField('Name', validators=[Required(), Length(1, 256)]) + project_name = StringField('Admin Project Name', validators=[Required(), Length(1, 128)]) + region = StringField('Region Name', validators=[Required(), Length(1, 128)]) + default_role = StringField('Default Role Name', validators=[Required(), Length(1, 128)]) + username = StringField('User Name', validators=[Required(), Length(1, 128)]) + password = PasswordField('Password', validators=[Required(), Length(1, 256)]) + api_version = StringField('API Version', validators=[Required(), Length(1, 64)]) + url = StringField('URL', validators=[Required(), Length(1, 256)]) + enabled = BooleanField('Enabled') + + def validate_name(self, field): + if Provider.query.filter_by(name=field.data).first(): + raise ValidationError('Provider name is already used. Use different name.') + +class EditProviderAdminForm(Form): + provider = SelectField('Provider', validators=[Required()], + choices=[('openstack', 'OpenStack'), ('other', 'Other')]) + name = StringField('Name', validators=[Required(), Length(1, 128)]) + project_name = StringField('Tenant Name', validators=[Required(), Length(1, 128)]) + region = StringField('Region Name', validators=[Required(), Length(1, 128)]) + default_role = StringField('Default Role Name', validators=[Required(), Length(1, 128)]) + username = StringField('User Name', validators=[Required(), Length(1, 128)]) + password = PasswordField('Password', validators=[Required(), Length(1, 256)]) + api_version = StringField('API Version', validators=[Required(), Length(1, 64)]) + url = StringField('URL', validators=[Required(), Length(1, 256)]) + enabled = BooleanField('Enabled') + +class DeleteProviderAdminForm(Form): + confirm = BooleanField('Confirmed', validators=[Required(message='You must confirm to delete.')]) + +class ValidateProviderAdminForm(Form): + provider = SelectField('Provider', coerce=int) + confirm = BooleanField('Confirmed', validators=[Required(message='You must confirm to delete.')]) + + def __init__(self, provider, *args, **kwargs): + super(ValidateProviderAdminForm, self).__init__(*args, **kwargs) + self.provider.choices = [(provider.id, provider.name) + for provider in Provider.query.order_by(Provider.name).all()] \ No newline at end of file diff --git a/dash/admin/helpers.py b/dash/admin/helpers.py new file mode 100644 index 0000000..eb4041e --- /dev/null +++ b/dash/admin/helpers.py @@ -0,0 +1,23 @@ +import requests, json + +from openstack import connection, profile + +from ..models import Provider + + +class Connect(): + def create_connection(self, auth_url, region, project_name, username, password): + prof = profile.Profile() + prof.set_version('identity', 'v3') + prof.set_api_version('identity','v3') + prof.set_region(profile.Profile.ALL, region) + + return connection.Connection( + profile=prof, + user_agent='examples', + auth_url=auth_url, + identity_api_version='3', + project_name=project_name, + username=username, + password=password + ) \ No newline at end of file diff --git a/dash/admin/helpers.py.back b/dash/admin/helpers.py.back new file mode 100644 index 0000000..2710d16 --- /dev/null +++ b/dash/admin/helpers.py.back @@ -0,0 +1,86 @@ +import requests, json + +from ..models import Provider + +# OpenStack Identity V3 API Calls +class Identity: + def auth_unscoped(self, auth_url, username, password, domain): + payload = { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "name": username, + "domain": { + "id": domain + }, + "password": password + } + } + } + } + } + auth_url = "%s/v3/auth/tokens" %(auth_url) + resp = requests.session() + resp = resp.post(auth_url, data=json.dumps(payload)) + return resp + + def auth_unscoped_token(self, auth_url, provider_id): + provider = Provider.query.get_or_404(provider_id) + payload = { + "auth": { + "identity": { + "methods": [ + "token" + ], + "token": { + "id": provider.x_subject_token + } + } + } + } + auth_url = "%s/v3/auth/tokens" %(auth_url) + resp = requests.session() + resp = resp.post(auth_url, data=json.dumps(payload)) + return resp + + def auth_scoped(self, auth_url, username, password, domain): + payload = { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "name": username, + "password": password + } + } + }, + "scope": { + "project": { + "name": project + } + } + } + } + auth_url = "%s/v3/auth/tokens" %(auth_url) + resp = requests.post(auth_url, data=json.dumps(payload)) + return resp + + def auth_validate_show_token(self, auth_url, provider_id): + provider = Provider.query.get_or_404(provider_id) + headers = {'X-Auth-Token': provider.x_subject_token , 'X-Subject-Token': provider.x_subject_token} + auth_url = "%s/v3/auth/tokens" % (auth_url) + resp = requests.get(auth_url, headers=headers) + return resp + + def list_projects(self, url, x_subject_token): + headers = {'X-Auth-Token': x_subject_token} + auth_url = "%s/v3/projects" % (url) + resp = requests.get(auth_url, headers=json.dumps(headers)) + return resp \ No newline at end of file diff --git a/dash/admin/views.py b/dash/admin/views.py index b3c1757..fec8cbe 100644 --- a/dash/admin/views.py +++ b/dash/admin/views.py @@ -1,4 +1,8 @@ -import datetime +import datetime, requests, json, string, random + +from keystoneauth1.identity import v3 +from keystoneauth1 import session +from keystoneclient.v3 import client from flask import render_template, redirect, request, url_for, flash from flask_login import login_user, logout_user, login_required, \ @@ -8,11 +12,13 @@ from flask_principal import Identity, AnonymousIdentity, \ from . import admin from .. import db -from ..models import User, Role +from ..models import User, Role, Provider from ..email import send_email from ..decorators import requires_roles from .forms import EditUserAdminForm, CreateUserAdminForm, CreateUserAdminForm, \ - DeleteUserAdminForm + DeleteUserAdminForm, CreateProviderAdminForm, EditProviderAdminForm, \ + DeleteProviderAdminForm, ValidateProviderAdminForm, \ + CreateUserProviderAdminForm @admin.route('/') @login_required @@ -51,6 +57,50 @@ def create_user_admin(): return render_template('admin/create_user.html', form=form, title="Create New User", block_description = "fill all the fields to create new user") + +@admin.route('/create-user-provider/', methods=['GET', 'POST']) +@login_required +@requires_roles("admin") +def create_user_provider_admin(id): + user = User.query.get_or_404(id) + providers = Provider.query.all() + form = CreateUserProviderAdminForm(user=user) + if form.validate_on_submit(): + if len(user.provider_password) != 24: + chars = string.letters + string.digits + string.punctuation + user.provider_password = ''.join((random.choice(chars)) for x in range(24)) + db.session.add(user) + # make openstack api connection for chosen provider + provider = Provider.query.get_or_404(form.provider.data) + auth = v3.Password(auth_url=provider.url, + username=provider.username, + password=provider.password, + project_id=provider.project_name, + user_domain_name='Default') + sess = session.Session(auth=auth) + keystone = client.Client(session=sess) + # create project + project = keystone.projects.create(user.username, + 'default', + enabled=True) + # creates user + user = keystone.users.create(user.username, + password=user.provider_password, + email=user.email, + enabled=True, + default_project=user.username) + role_search = keystone.roles.list(name=provider.default_role) + role_id = role_search[0].id + role = keystone.roles.grant(role_id, + user=user.id, + project=project.id) + return render_template('admin/create_user_provider.html', user=user, form=form, + title="Create User on Provider", providers=providers, + project=project,role=role, + block_description = "create a user account on selected cloud provider") + return render_template('admin/create_user_provider.html', user=user, form=form, + title="Create User on Provider", providers=providers, + block_description = "create a user account on selected cloud provider") @admin.route('/edit-user/', methods=['GET', 'POST']) @login_required @@ -87,4 +137,99 @@ def delete_user_admin(id): return redirect(url_for('.index')) return render_template('admin/delete_user.html', user=user, form=form, title="Delete User", - block_description = "delete user confirmation") \ No newline at end of file + block_description = "delete user confirmation") + +@admin.route('/list-providers') +@login_required +@requires_roles("admin") +def list_providers(): + providers = Provider.query.all() + return render_template('admin/list_providers.html', providers=providers, + title="List Providers", + block_description = "list, edit and delete providers") + +@admin.route('/create-provider', methods=['GET', 'POST']) +@login_required +@requires_roles("admin") +def create_provider_admin(): + form = CreateProviderAdminForm() + if form.validate_on_submit(): + provider = Provider(provider=form.provider.data, + name=form.name.data, + project_name=form.project_name.data, + default_role=form.default_role.data, + username=form.username.data, + password=form.password.data, + api_version=form.api_version.data, + url=form.url.data, + created_at=datetime.datetime.now(), + enabled=form.enabled.data) + db.session.add(provider) + db.session.commit() + flash('New provider created.') + return redirect(url_for('.edit_provider_admin', id=provider.id)) + return render_template('admin/create_provider.html', form=form, + title="Create New Provider", + block_description = "add your new cloud provider") + +@admin.route('/edit-provider/', methods=['GET', 'POST']) +@login_required +@requires_roles("admin") +def edit_provider_admin(id): + provider = Provider.query.get_or_404(id) + form = EditProviderAdminForm(provider=provider) + if form.validate_on_submit(): + provider.provider = form.provider.data + provider.name = form.name.data + provider.project_name = form.project_name.data + provider.region = form.region.data + provider.default_role=form.default_role.data + provider.username = form.username.data + provider.password = form.password.data + provider.api_version = form.api_version.data + provider.url = form.url.data + provider.enabled = form.enabled.data + db.session.add(provider) + flash('The provider has been updated.') + return redirect(url_for('.edit_provider_admin', id=provider.id)) + return render_template('admin/edit_provider.html', provider=provider, form=form, + title="Edit Provider", + block_description = "edit and update provider info") + +@admin.route('/delete-provider/', methods=['GET', 'POST']) +@login_required +@requires_roles("admin") +def delete_provider_admin(id): + provider = Provider.query.get_or_404(id) + form = DeleteProviderAdminForm(provider=provider) + if form.validate_on_submit(): + db.session.delete(provider) + db.session.commit() + flash('The provider has been deleted.') + return redirect(url_for('.index')) + return render_template('admin/delete_provider.html', provider=provider, form=form, + title="Delete Provider", + block_description = "delete provider confirmation") + +@admin.route('/validate-provider/', methods=['GET', 'POST']) +@login_required +@requires_roles("admin") +def validate_provider_admin(id): + provider = Provider.query.get_or_404(id) + auth = v3.Password(auth_url=provider.url, + username=provider.username, + password=provider.password, + project_id=provider.project_name, + user_domain_name='Default') + sess = session.Session(auth=auth) + keystone = client.Client(session=sess) + roles = keystone.roles.list(name='_member_') + role_id = roles[0].id + roles_type = type(roles) + project = keystone.projects.list(name='admin') + projects = 'projects' + return render_template('admin/validate_provider.html', provider=provider, + title="Validate Provider", #projects=projects, + role_id=role_id, + keystone=keystone, roles=roles, project=project, roles_type=roles_type, + block_description = "validate provider") \ No newline at end of file diff --git a/dash/models.py b/dash/models.py index 84df808..59237c8 100644 --- a/dash/models.py +++ b/dash/models.py @@ -34,6 +34,7 @@ class User(UserMixin, db.Model): avatar = db.Column(db.String(255), index=True) created_at = db.Column(db.DateTime) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) + provider_password = db.Column(db.Text(255)) confirmed = db.Column(db.Boolean, default=False) suspended = db.Column(db.Boolean, default=False) @@ -108,6 +109,24 @@ class User(UserMixin, db.Model): def __repr__(self): return '' % self.username +class Provider(db.Model): + __tablename__ = 'providers' + + id = db.Column(db.Integer, primary_key=True) + provider = db.Column(db.String(128), unique=False, index=True) + name = db.Column(db.String(128), unique=True, index=True) + region = db.Column(db.String(128), unique=False, index=True) + project_name = db.Column(db.String(128), unique=False, index=True) + default_role = db.Column(db.String(128), unique=False, index=True) + username = db.Column(db.String(128), unique=False, index=True) + api_version = db.Column(db.String(64), unique=False, index=True) + password = db.Column(db.Text(255), unique=False, index=False) + url = db.Column(db.Text(512)) + created_at = db.Column(db.DateTime) + enabled = db.Column(db.Boolean, default=True, nullable=False) + validated = db.Column(db.Boolean, default=False, nullable=False) + + @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) \ No newline at end of file diff --git a/dash/templates/admin/create_provider.html b/dash/templates/admin/create_provider.html new file mode 100644 index 0000000..ca9b3e0 --- /dev/null +++ b/dash/templates/admin/create_provider.html @@ -0,0 +1,132 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} +{% from "_formhelpers.html" import render_field %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
+
+
+ +
+
+ {{ form.hidden_tag() }} +
+ + + {% if form.provider.errors %} + {% for error in form.provider.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.name.errors %} + {% for error in form.name.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.region.errors %} + {% for error in form.region.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.username.errors %} + {% for error in form.username.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.project_name.errors %} + {% for error in form.project_name.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.default_role.errors %} + {% for error in form.default_role.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.api_version.errors %} + {% for error in form.api_version.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.url.errors %} + {% for error in form.url.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.password.errors %} + {% for error in form.password.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+
+
+ + {% if form.enabled.errors %} +
+ {% for error in form.enabled.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+ + +{%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/create_user_provider.html b/dash/templates/admin/create_user_provider.html new file mode 100644 index 0000000..adf0b34 --- /dev/null +++ b/dash/templates/admin/create_user_provider.html @@ -0,0 +1,89 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} +{% from "_formhelpers.html" import render_field %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
+
+
+ +
+ +

Select Cloud Proivder and Create User Account

+
+ +
+
+ {{ form.hidden_tag() }} +
+
+
+ + + + {% if form.provider.errors %} + {% for error in form.provider.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ +
+ + +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+

Result

+ {% if project %} + {{ project }}
+ {{ user }}
+ {% endif %} +
+
+
+
+
+ +{%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/delete_provider.html b/dash/templates/admin/delete_provider.html new file mode 100644 index 0000000..9a0a7a7 --- /dev/null +++ b/dash/templates/admin/delete_provider.html @@ -0,0 +1,84 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} +{% from "_formhelpers.html" import render_field %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
+
+
+ +
+ + +

You are Warned

+
+ +
+
+

Provider Delete Alert!

+ Your are about to delete cloud provider "{{ provider.name }}" from database. + You will not able to undo this action. +
+ Are you sure you want to delete this provider? +
+
+ +
+ +
+
+ {{ form.hidden_tag() }} +
+
+
+ + {% if form.confirm.errors %} +
+ {% for error in form.confirm.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ + + + +{%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/edit_provider.html b/dash/templates/admin/edit_provider.html new file mode 100644 index 0000000..de0f292 --- /dev/null +++ b/dash/templates/admin/edit_provider.html @@ -0,0 +1,132 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} +{% from "_formhelpers.html" import render_field %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
+
+
+ +
+
+ {{ form.hidden_tag() }} +
+ + + {% if form.provider.errors %} + {% for error in form.provider.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.name.errors %} + {% for error in form.name.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.region.errors %} + {% for error in form.region.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.username.errors %} + {% for error in form.username.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.project_name.errors %} + {% for error in form.project_name.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.default_role.errors %} + {% for error in form.default_role.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.api_version.errors %} + {% for error in form.api_version.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.url.errors %} + {% for error in form.url.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ + + {% if form.password.errors %} + {% for error in form.password.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+
+
+ + {% if form.enabled.errors %} +
+ {% for error in form.enabled.errors %} {{ error }} {% endfor %} + {% endif %} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+ + +{%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/edit_user.html b/dash/templates/admin/edit_user.html index 69c2f3d..d69a3f3 100644 --- a/dash/templates/admin/edit_user.html +++ b/dash/templates/admin/edit_user.html @@ -31,7 +31,6 @@
-
{{ form.hidden_tag() }} @@ -103,5 +102,15 @@
+ {%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/list_providers.html b/dash/templates/admin/list_providers.html new file mode 100644 index 0000000..a639db4 --- /dev/null +++ b/dash/templates/admin/list_providers.html @@ -0,0 +1,87 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
+
+
+ +
+ + + + + + + + + + + + + + {% for provider in providers %} + + + + + + + + + + {% endfor %} + + + + + + + + + + + + +
IDProviderNameTenant NameUser NameAPI VersionAction
{{ provider.id }}{{ provider.provider }}{{ provider.name }}{{ provider.project_name }}{{ provider.username }}{{ provider.api_version }} + Edit + | + Delete + | + Validate +
IDProviderNameTenant NameUser NameAPI VersionAction
+
+ +
+ +
+ +
+ + +{%- endblock content %} \ No newline at end of file diff --git a/dash/templates/admin/sidebar_menu.html b/dash/templates/admin/sidebar_menu.html index 73ce766..c44269a 100644 --- a/dash/templates/admin/sidebar_menu.html +++ b/dash/templates/admin/sidebar_menu.html @@ -5,7 +5,7 @@ Admin Dashboard
- +
  • @@ -33,4 +33,27 @@
  • + + +
  • + + + Providers + + + +
  • \ No newline at end of file diff --git a/dash/templates/admin/validate_provider.html b/dash/templates/admin/validate_provider.html new file mode 100644 index 0000000..669133a --- /dev/null +++ b/dash/templates/admin/validate_provider.html @@ -0,0 +1,55 @@ +{% extends "adminlte/base.html" %} +{% import "adminlte/layout.html" as layout with context %} +{% import "adminlte/widgets.html" as widgets with context %} +{% from "_formhelpers.html" import render_field %} + +{% block title %}Admin - {{ title }}{% endblock %} +{% block description %}{{ block_description }}{% endblock %} + +{% block navbar %} + + {% include "navbar.html" %} + +{%- endblock navbar %} + + +{% block sidebar -%} + + {% include 'sidebar.html' %} + + {% include 'admin/sidebar_menu.html' %} + +{%- endblock sidebar %} + + +{% block content_header -%} + {% include 'admin/content_header.html' %} +{%- endblock content_header %} + +{% block content -%} + +
    +
    +
    + +
    + Validating: {{provider.name}} - {{ provider.url }}
    +
    + {{ project[0]['id'] }}
    + {{ role_id }} +
    + {{ roles_type }}
    + {% for r in roles %} + {{ r['id'] }} + {% endfor %} +
    +
    + +
    + +
    + +
    + + +{%- endblock content %} \ No newline at end of file diff --git a/migrations/versions/5cc72c718d14_.py b/migrations/versions/2b52e8261507_.py similarity index 54% rename from migrations/versions/5cc72c718d14_.py rename to migrations/versions/2b52e8261507_.py index c4e8baa..3cc0e90 100644 --- a/migrations/versions/5cc72c718d14_.py +++ b/migrations/versions/2b52e8261507_.py @@ -1,14 +1,14 @@ """empty message -Revision ID: 5cc72c718d14 -Revises: ad5c9cae2c6d -Create Date: 2016-08-24 22:56:39.588007 +Revision ID: 2b52e8261507 +Revises: 9f9f6374b616 +Create Date: 2016-08-27 17:17:07.016592 """ # revision identifiers, used by Alembic. -revision = '5cc72c718d14' -down_revision = 'ad5c9cae2c6d' +revision = '2b52e8261507' +down_revision = '9f9f6374b616' from alembic import op import sqlalchemy as sa @@ -16,11 +16,11 @@ import sqlalchemy as sa def upgrade(): ### commands auto generated by Alembic - please adjust! ### - op.add_column('users', sa.Column('suspended', sa.Boolean(), nullable=True)) + op.add_column('users', sa.Column('provider_password', sa.String(length=128), nullable=True)) ### end Alembic commands ### def downgrade(): ### commands auto generated by Alembic - please adjust! ### - op.drop_column('users', 'suspended') + op.drop_column('users', 'provider_password') ### end Alembic commands ### diff --git a/migrations/versions/48c96b4cae0c_.py b/migrations/versions/48c96b4cae0c_.py new file mode 100644 index 0000000..399c099 --- /dev/null +++ b/migrations/versions/48c96b4cae0c_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: 48c96b4cae0c +Revises: 73982db0bb88 +Create Date: 2016-08-31 21:53:02.488962 + +""" + +# revision identifiers, used by Alembic. +revision = '48c96b4cae0c' +down_revision = '73982db0bb88' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('default_role', sa.String(length=128), nullable=True)) + op.create_index(op.f('ix_providers_default_role'), 'providers', ['default_role'], unique=False) + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_index(op.f('ix_providers_default_role'), table_name='providers') + op.drop_column('providers', 'default_role') + ### end Alembic commands ### diff --git a/migrations/versions/56c33e417a5c_.py b/migrations/versions/56c33e417a5c_.py new file mode 100644 index 0000000..ac57241 --- /dev/null +++ b/migrations/versions/56c33e417a5c_.py @@ -0,0 +1,26 @@ +"""empty message + +Revision ID: 56c33e417a5c +Revises: ede7ee3212ad +Create Date: 2016-08-28 15:55:11.835537 + +""" + +# revision identifiers, used by Alembic. +revision = '56c33e417a5c' +down_revision = 'ede7ee3212ad' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('x_session_token', sa.Text(length=255), nullable=True)) + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_column('providers', 'x_session_token') + ### end Alembic commands ### diff --git a/migrations/versions/73982db0bb88_.py b/migrations/versions/73982db0bb88_.py new file mode 100644 index 0000000..1530d00 --- /dev/null +++ b/migrations/versions/73982db0bb88_.py @@ -0,0 +1,30 @@ +"""empty message + +Revision ID: 73982db0bb88 +Revises: ad4bacc19155 +Create Date: 2016-08-28 21:51:42.194149 + +""" + +# revision identifiers, used by Alembic. +revision = '73982db0bb88' +down_revision = 'ad4bacc19155' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('region', sa.String(length=128), nullable=True)) + op.create_index(op.f('ix_providers_region'), 'providers', ['region'], unique=False) + op.drop_column('providers', 'x_subject_token') + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('x_subject_token', mysql.TEXT(collation=u'utf8_bin'), nullable=True)) + op.drop_index(op.f('ix_providers_region'), table_name='providers') + op.drop_column('providers', 'region') + ### end Alembic commands ### diff --git a/migrations/versions/070b614d54f1_.py b/migrations/versions/9f9f6374b616_.py similarity index 54% rename from migrations/versions/070b614d54f1_.py rename to migrations/versions/9f9f6374b616_.py index 0657f39..b444554 100644 --- a/migrations/versions/070b614d54f1_.py +++ b/migrations/versions/9f9f6374b616_.py @@ -1,13 +1,13 @@ """empty message -Revision ID: 070b614d54f1 +Revision ID: 9f9f6374b616 Revises: None -Create Date: 2016-08-07 18:01:50.124123 +Create Date: 2016-08-25 22:48:06.893609 """ # revision identifiers, used by Alembic. -revision = '070b614d54f1' +revision = '9f9f6374b616' down_revision = None from alembic import op @@ -16,11 +16,29 @@ import sqlalchemy as sa def upgrade(): ### commands auto generated by Alembic - please adjust! ### + op.create_table('providers', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('provider', sa.String(length=128), nullable=True), + sa.Column('name', sa.String(length=128), nullable=True), + sa.Column('tenant_name', sa.String(length=128), nullable=True), + sa.Column('username', sa.String(length=128), nullable=True), + sa.Column('api_version', sa.String(length=64), nullable=True), + sa.Column('password', sa.Text(length=256), nullable=True), + sa.Column('url', sa.Text(length=512), nullable=True), + sa.Column('created_at', sa.DateTime(), nullable=True), + sa.Column('enabled', sa.Boolean(), default=True, nullable=False), + sa.Column('validated', sa.Boolean(), default=False, nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_providers_api_version'), 'providers', ['api_version'], unique=False) + op.create_index(op.f('ix_providers_name'), 'providers', ['name'], unique=True) + op.create_index(op.f('ix_providers_provider'), 'providers', ['provider'], unique=False) + op.create_index(op.f('ix_providers_tenant_name'), 'providers', ['tenant_name'], unique=False) + op.create_index(op.f('ix_providers_username'), 'providers', ['username'], unique=False) op.create_table('roles', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.String(length=128), nullable=True), sa.Column('default', sa.Boolean(), nullable=True), - sa.Column('permissions', sa.Integer(), nullable=True), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('name') ) @@ -35,6 +53,7 @@ def upgrade(): sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('role_id', sa.Integer(), nullable=True), sa.Column('confirmed', sa.Boolean(), nullable=True), + sa.Column('suspended', sa.Boolean(), nullable=True), sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ), sa.PrimaryKeyConstraint('id') ) @@ -54,4 +73,10 @@ def downgrade(): op.drop_table('users') op.drop_index(op.f('ix_roles_default'), table_name='roles') op.drop_table('roles') + op.drop_index(op.f('ix_providers_username'), table_name='providers') + op.drop_index(op.f('ix_providers_tenant_name'), table_name='providers') + op.drop_index(op.f('ix_providers_provider'), table_name='providers') + op.drop_index(op.f('ix_providers_name'), table_name='providers') + op.drop_index(op.f('ix_providers_api_version'), table_name='providers') + op.drop_table('providers') ### end Alembic commands ### diff --git a/migrations/versions/ad4bacc19155_.py b/migrations/versions/ad4bacc19155_.py new file mode 100644 index 0000000..5e535e0 --- /dev/null +++ b/migrations/versions/ad4bacc19155_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: ad4bacc19155 +Revises: 56c33e417a5c +Create Date: 2016-08-28 16:08:23.350311 + +""" + +# revision identifiers, used by Alembic. +revision = 'ad4bacc19155' +down_revision = '56c33e417a5c' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('x_subject_token', sa.Text(length=255), nullable=True)) + op.drop_column('providers', 'x_session_token') + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('x_session_token', mysql.TEXT(collation=u'utf8_bin'), nullable=True)) + op.drop_column('providers', 'x_subject_token') + ### end Alembic commands ### diff --git a/migrations/versions/ad5c9cae2c6d_.py b/migrations/versions/ad5c9cae2c6d_.py deleted file mode 100644 index da37f1f..0000000 --- a/migrations/versions/ad5c9cae2c6d_.py +++ /dev/null @@ -1,26 +0,0 @@ -"""empty message - -Revision ID: ad5c9cae2c6d -Revises: 070b614d54f1 -Create Date: 2016-08-07 18:16:57.701675 - -""" - -# revision identifiers, used by Alembic. -revision = 'ad5c9cae2c6d' -down_revision = '070b614d54f1' - -from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import mysql - -def upgrade(): - ### commands auto generated by Alembic - please adjust! ### - op.drop_column('roles', 'permissions') - ### end Alembic commands ### - - -def downgrade(): - ### commands auto generated by Alembic - please adjust! ### - op.add_column('roles', sa.Column('permissions', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True)) - ### end Alembic commands ### diff --git a/migrations/versions/ede7ee3212ad_.py b/migrations/versions/ede7ee3212ad_.py new file mode 100644 index 0000000..d6ea402 --- /dev/null +++ b/migrations/versions/ede7ee3212ad_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: ede7ee3212ad +Revises: 2b52e8261507 +Create Date: 2016-08-27 17:38:36.769787 + +""" + +# revision identifiers, used by Alembic. +revision = 'ede7ee3212ad' +down_revision = '2b52e8261507' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('project_name', sa.String(length=128), nullable=True)) + op.create_index(op.f('ix_providers_project_name'), 'providers', ['project_name'], unique=False) + op.drop_index('ix_providers_tenant_name', table_name='providers') + op.drop_column('providers', 'tenant_name') + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('providers', sa.Column('tenant_name', mysql.VARCHAR(collation=u'utf8_bin', length=128), nullable=True)) + op.create_index('ix_providers_tenant_name', 'providers', ['tenant_name'], unique=False) + op.drop_index(op.f('ix_providers_project_name'), table_name='providers') + op.drop_column('providers', 'project_name') + ### end Alembic commands ### diff --git a/requirements.txt b/requirements.txt index ca581bc..8e93e70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,4 +15,5 @@ Werkzeug alembic blinker itsdangerous -flask-principal \ No newline at end of file +flask-principal +requests \ No newline at end of file