WIP: Support local accounts #13
					 6 changed files with 101 additions and 5 deletions
				
			
		| 
						 | 
					@ -10,9 +10,12 @@ bp = Blueprint('auth', __name__, url_prefix='/auth')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from acmsite import oauth
 | 
					from acmsite import oauth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route("/login")
 | 
				
			||||||
@bp.route('/login')
 | 
					 | 
				
			||||||
def login():
 | 
					def login():
 | 
				
			||||||
 | 
					    return render_template('login.html')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route('/oauth')
 | 
				
			||||||
 | 
					def oauth_redirect():
 | 
				
			||||||
    return oauth.azure.authorize_redirect(url_for('auth.oauth2_callback',
 | 
					    return oauth.azure.authorize_redirect(url_for('auth.oauth2_callback',
 | 
				
			||||||
                                                  _external=True))
 | 
					                                                  _external=True))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,39 @@
 | 
				
			||||||
 | 
					from werkzeug.security import generate_password_hash, check_password_hash
 | 
				
			||||||
 | 
					from flask import Blueprint, render_template, request, flash, redirect, url_for
 | 
				
			||||||
 | 
					from flask_login import current_user, login_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from flask import Blueprint, render_template
 | 
					from acmsite.dashboard.forms import PasswordForm
 | 
				
			||||||
 | 
					from acmsite import db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bp = Blueprint('dashboard', __name__, url_prefix='/dashboard')
 | 
					bp = Blueprint('dashboard', __name__, url_prefix='/dashboard')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route("/")
 | 
					@bp.route("/")
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
def home():
 | 
					def home():
 | 
				
			||||||
    return render_template('dashboard.html')
 | 
					    form = PasswordForm()
 | 
				
			||||||
 | 
					    return render_template('dashboard.html', form=form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route("/change_password", methods=["POST"])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def change_password():
 | 
				
			||||||
 | 
					    form = PasswordForm(request.form)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if form.validate_on_submit():
 | 
				
			||||||
 | 
					        current_password = request.form.get("current_password")
 | 
				
			||||||
 | 
					        new_password = request.form.get("new_password")
 | 
				
			||||||
 | 
					        password_confirm = request.form.get("password_confirm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if new_password == password_confirm:
 | 
				
			||||||
 | 
					            if current_password == '' and current_user.password == '':
 | 
				
			||||||
 | 
					                current_user.password = generate_password_hash(new_password)
 | 
				
			||||||
 | 
					                flash("Password set successfully.")
 | 
				
			||||||
 | 
					            elif check_password_hash(current_user.password, current_password):
 | 
				
			||||||
 | 
					                current_user.password = generate_password_hash(new_password)
 | 
				
			||||||
 | 
					                flash("Password updated successfully.")
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                flash("Incorrect password.")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            flash("Passwords do not match!")
 | 
				
			||||||
 | 
					        db.session.commit()
 | 
				
			||||||
 | 
					        return redirect(url_for("dashboard.home"))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								acmsite/dashboard/forms.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								acmsite/dashboard/forms.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					from flask_wtf import FlaskForm
 | 
				
			||||||
 | 
					from wtforms.fields import PasswordField
 | 
				
			||||||
 | 
					from wtforms.validators import DataRequired
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PasswordForm(FlaskForm):
 | 
				
			||||||
 | 
					    current_password = PasswordField('Current Password')
 | 
				
			||||||
 | 
					    new_password = PasswordField('New Password', validators=[DataRequired()])
 | 
				
			||||||
 | 
					    password_confirm = PasswordField('Confirm New Password',
 | 
				
			||||||
 | 
					                                     validators=[DataRequired()])
 | 
				
			||||||
| 
						 | 
					@ -13,4 +13,46 @@
 | 
				
			||||||
                                                          unless you're an
 | 
					                                                          unless you're an
 | 
				
			||||||
                                                          officer!</p>
 | 
					                                                          officer!</p>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					<button type="button" class="btn btn-secondary" data-bs-toggle="modal"
 | 
				
			||||||
 | 
					                                  data-bs-target="#passwordModal">Change or Set
 | 
				
			||||||
 | 
					                                  Local Password</button>
 | 
				
			||||||
 | 
					<!-- Modals -->
 | 
				
			||||||
 | 
					<div class="modal" id="passwordModal" tabindex="-1" aria-labelledby="passwordModalLabel"
 | 
				
			||||||
 | 
					                                                aria-hidden="true">
 | 
				
			||||||
 | 
					      <div class="modal-dialog">
 | 
				
			||||||
 | 
					    <div class="modal-content">
 | 
				
			||||||
 | 
					      <div class="modal-header">
 | 
				
			||||||
 | 
					        <h1 class="modal-title fs-5" id="passwordModalLabel">Change Password</h1>
 | 
				
			||||||
 | 
					        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <form class="form" id="edit-form" action="/dashboard/change_password" role="form" method="post">
 | 
				
			||||||
 | 
					          <div class="modal-body">
 | 
				
			||||||
 | 
					          {{ form.csrf_token }}
 | 
				
			||||||
 | 
					            <div class="form-floating mb-3 required">
 | 
				
			||||||
 | 
					                {{ form.current_password(class="form-control") }}
 | 
				
			||||||
 | 
					                {{ form.current_password.label() }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					           <div class="row">
 | 
				
			||||||
 | 
					                <div class="col">
 | 
				
			||||||
 | 
					                    <div class="form-floating mb-3 required">
 | 
				
			||||||
 | 
					                        {{ form.new_password(class="form-control") }}
 | 
				
			||||||
 | 
					                        {{ form.new_password.label() }}
 | 
				
			||||||
 | 
					                    </div> 
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="col">
 | 
				
			||||||
 | 
					                    <div class="form-floating mb-3 required">
 | 
				
			||||||
 | 
					                        {{ form.password_confirm(class="form-control") }}
 | 
				
			||||||
 | 
					                        {{ form.password_confirm.label() }}
 | 
				
			||||||
 | 
					                    </div>                    
 | 
				
			||||||
 | 
					                </div> 
 | 
				
			||||||
 | 
					            </div> 
 | 
				
			||||||
 | 
					         </div>
 | 
				
			||||||
 | 
					          <div class="modal-footer">
 | 
				
			||||||
 | 
					            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
 | 
				
			||||||
 | 
					            <button type="submit" class="btn btn-primary" id="edit-save">Save changes</button>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					      </form>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
{% endblock app_content %}
 | 
					{% endblock app_content %}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@
 | 
				
			||||||
                    {% endif %}  
 | 
					                    {% endif %}  
 | 
				
			||||||
                    {{ render_nav_item('auth.logout', 'Logout') }}
 | 
					                    {{ render_nav_item('auth.logout', 'Logout') }}
 | 
				
			||||||
                {% else %}
 | 
					                {% else %}
 | 
				
			||||||
                    {{ render_nav_item('auth.login', 'Login with WPI') }}
 | 
					                    {{ render_nav_item('auth.login', 'Login') }}
 | 
				
			||||||
                {% endif %}
 | 
					                {% endif %}
 | 
				
			||||||
            </ul>
 | 
					            </ul>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								acmsite/templates/login.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								acmsite/templates/login.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					{% extends "layout.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block app_content %}
 | 
				
			||||||
 | 
					<h1>Login Methods</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					<a class="btn btn-primary" href="{{ url_for('auth.oauth_redirect') }}">Login with WPI</a>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<div class="mt-1 mb-3">
 | 
				
			||||||
 | 
					<a class="btn btn-secondary" href="">Login with Local Account</a>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock app_content %}
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue