예제 #1
0
파일: Model.php 프로젝트: DavBfr/BlogMVC
 public function save(array $properties, $key = null, array $options = [])
 {
     if (empty($properties['slug'])) {
         $properties['slug'] = \ICanBoogie\normalize($properties['name']);
     }
     return parent::save($properties, $key, $options);
 }
예제 #2
0
 /**
  * Renders selected widgets.
  *
  * @see Icybee\Modules\Editor.Editor::render()
  */
 public function render($content)
 {
     global $core;
     if (!$content) {
         return;
     }
     $availables = $core->configs->synthesize('widgets', 'merge');
     if (!$availables) {
         return;
     }
     $selected = array_flip($content);
     $undefined = array_diff_key($selected, $availables);
     if ($undefined) {
         throw new Exception('Undefined widget(s): :list', array(':list' => implode(', ', array_keys($undefined))));
     }
     $list = array_intersect_key($availables, $selected);
     if (!$list) {
         return;
     }
     $html = '';
     $list = array_merge($selected, $list);
     foreach ($list as $id => $widget) {
         $html .= '<div id="widget-' . \ICanBoogie\normalize($id) . '" class="widget">' . $this->render_widget($widget, $id) . '</div>';
     }
     return $html;
 }
예제 #3
0
    protected function validate(\ICanboogie\Errors $errors)
    {
        global $core;
        $request = $this->request;
        $username = $request[User::USERNAME];
        $password = $request[User::PASSWORD];
        $uid = $core->models['users']->select('uid')->where('username = ? OR email = ?', $username, $username)->rc;
        if (!$uid) {
            $errors[User::PASSWORD] = new FormattedString('Unknown username/password combination.');
            return false;
        }
        $user = $core->models['users'][$uid];
        $now = time();
        $login_unlock_time = $user->metas['login_unlock_time'];
        if ($login_unlock_time) {
            if ($login_unlock_time > $now) {
                throw new \ICanBoogie\HTTP\HTTPError(\ICanBoogie\format("The user account has been locked after multiple failed login attempts.\n\t\t\t\t\tAn e-mail has been sent to unlock the account. Login attempts are locked until %time,\n\t\t\t\t\tunless you unlock the account using the email sent.", ['%count' => $user->metas['failed_login_count'], '%time' => I18n\format_date($login_unlock_time, 'HH:mm')]), 403);
            }
            $user->metas['login_unlock_time'] = null;
        }
        if (!$user->verify_password($password)) {
            $errors[User::PASSWORD] = new FormattedString('Unknown username/password combination.');
            $user->metas['failed_login_count'] += 1;
            $user->metas['failed_login_time'] = $now;
            if ($user->metas['failed_login_count'] >= 10) {
                $token = \ICanBoogie\generate_token(40, \ICanBoogie\TOKEN_ALPHA . \ICanBoogie\TOKEN_NUMERIC);
                $user->metas['login_unlock_token'] = $token;
                $user->metas['login_unlock_time'] = $now + 3600;
                $until = I18n\format_date($now + 3600, 'HH:mm');
                $url = $core->site->url . '/api/users/unlock_login?' . http_build_query(['username' => $username, 'token' => $token, 'continue' => $request->uri]);
                $t = new Proxi(['scope' => [\ICanBoogie\normalize($user->constructor, '_'), 'connect', 'operation']]);
                $core->mail(['destination' => $user->email, 'from' => 'no-reply@' . $_SERVER['HTTP_HOST'], 'subject' => "Your account has been locked", 'body' => <<<EOT
You receive this message because your account has been locked.

After multiple failed login attempts your account has been locked until {$until}. You can use the
following link to unlock your account and try to login again:

<{$url}>

If you forgot your password, you'll be able to request a new one.

If you didn't try to login neither forgot your password, this message might be the result of an
attack attempt on the website. If you think this is the case, please contact its admin.

The remote address of the request was: {$request->ip}.
EOT
]);
                unset($errors[User::PASSWORD]);
                $errors[] = new FormattedString("Your account has been locked, a message has been sent to your e-mail address.");
            }
            return false;
        }
        if (!$user->is_admin && !$user->is_activated) {
            $errors[] = new FormattedString('User %username is not activated', ['%username' => $username]);
            return false;
        }
        $this->record = $user;
        return true;
    }
예제 #4
0
 /**
  * Sends an email to the user requesting a nonce login.
  *
  * @param ProcessEvent $event
  * @param NonceLoginRequestOperation $target
  */
 public static function on_nonce_login_request(ProcessEvent $event, NonceLoginRequestOperation $target)
 {
     global $core;
     $user = $target->user;
     $ticket = $target->ticket;
     $route = $core->routes['api:nonce-login'];
     $url = $core->site->url . $route->format($ticket);
     $until = $ticket->expire_at->local->format('H:i');
     $t = new Proxi(array('scope' => \ICanBoogie\normalize($user->constructor, '_') . '.nonce_login_request.operation'));
     $core->mailer(array(Mailer::T_DESTINATION => $user->email, Mailer::T_FROM => $core->site->title . ' <no-reply@' . $_SERVER['HTTP_HOST'] . '>', Mailer::T_SUBJECT => $t('message.subject'), Mailer::T_MESSAGE => $t('message.template', array(':url' => $url, ':until' => $until, ':ip' => $event->request->ip))));
 }
예제 #5
0
 /**
  * If the `termslug` property is empty it is created from the `term` property, otherwise
  * the it is normalized.
  */
 public function save(array $properties, $key = null, array $options = array())
 {
     if (isset($properties[Term::TERM]) && empty($properties[Term::TERMSLUG])) {
         $properties[Term::TERMSLUG] = \Icybee\slugize($properties[Term::TERM]);
     } else {
         if (isset($properties[Term::TERMSLUG])) {
             $properties[Term::TERMSLUG] = \ICanBoogie\normalize($properties[Term::TERMSLUG]);
         }
     }
     return parent::save($properties, $key, $options);
 }
예제 #6
0
 /**
  * Defines an editable page content in a template.
  *
  * <pre>
  * <p:page:content
  *     id = qname
  *     title = string
  *     editor = string
  *     inherit = boolean>
  *     <!-- Content: with-param*, template? -->
  * </p:page:content>
  * </pre>
  *
  * The `id` attribute specifies the identifier of the content, it is required and must be
  * unique in the template. The `title` attribute specifies the label of the editor in the
  * page editor, it is required. The `editor` attribute specifies the editor to use to edit
  * the content, it is optional. The `inherit` attribute specifies that the content can be
  * inherited.
  *
  * Example:
  *
  * <pre>
  * <p:page:content id="body" title="Page body" />
  *
  * <p:page:content id="picture" title="Decorating picture" editor="image" inherit="inherit">
  * <img src="#{@path}" alt="#{@alt}" />
  * </p>
  *
  * </pre>
  *
  * @param array $args
  * @param \Patron\Engine $patron
  * @param mixed $template
  *
  * @return mixed
  */
 public static function markup_page_content(array $args, \Patron\Engine $patron, $template)
 {
     global $core;
     $render = $args['render'];
     if ($render === 'none') {
         return;
     }
     $page = $core->request->context->page;
     $contentid = $args['id'];
     $contents = array_key_exists($contentid, $page->contents) ? $page->contents[$contentid] : null;
     if (!$contents && !empty($args['inherit'])) {
         $node = $page->parent;
         while ($node) {
             $node_contents = $node->contents;
             if (empty($node_contents[$contentid])) {
                 $node = $node->parent;
                 continue;
             }
             $contents = $node_contents[$contentid];
             break;
         }
         #
         # maybe the home page define the contents, but because the home page is not the parent
         # of pages on single language sites, we have to check it now.
         #
         if (!$contents) {
             $node_contents = $page->home->contents;
             if (isset($node_contents[$contentid])) {
                 $contents = $node_contents[$contentid];
             }
         }
     }
     $editor = null;
     $rendered = null;
     if (is_string($contents)) {
         $rendered = $contents;
     } else {
         if ($contents) {
             $editor = $contents->editor;
             $rendered = $contents->render();
         }
     }
     if (!$rendered) {
         return;
     }
     $element = new Element('div', ['id' => 'content-' . $contentid, 'class' => 'editor-' . \ICanBoogie\normalize($editor)]);
     $patron->context['self']['element'] = $element;
     $rc = $template ? $patron($template, $rendered) : $rendered;
     if (!$rc) {
         return;
     }
     if (preg_match('#\\.html$#', $page->template) && empty($args['no-wrapper'])) {
         $element[Element::INNER_HTML] = $rc;
         $rc = $element;
     }
     $rc = self::handle_external_anchors($rc);
     return $rc;
 }
예제 #7
0
 /**
  * Returns the CSS class names of the node.
  *
  * @return array[string]mixed
  */
 protected function get_css_class_names()
 {
     $nid = $this->nid;
     $slug = $this->slug;
     return ['type' => 'node', 'id' => $nid ? "node-{$nid}" : null, 'slug' => $slug ? "node-slug-{$slug}" : null, 'constructor' => 'constructor-' . \ICanBoogie\normalize($this->constructor)];
 }
예제 #8
0
    /**
     * Renders the record into an HTML form.
     *
     * @return string
     */
    public function render()
    {
        global $core;
        #
        # if the form was sent successfully, we return the `complete` message instead of the form.
        #
        $session = $core->session;
        if (!empty($session->modules['forms']['rc'][$this->nid])) {
            unset($session->modules['forms']['rc'][$this->nid]);
            return '<div id="' . $this->slug . '">' . $this->complete . '</div>';
        }
        $form = $this->form;
        if (isset($form->hiddens[Operation::DESTINATION]) && isset($form->hiddens[Operation::NAME])) {
            $destination = $form->hiddens[Operation::DESTINATION];
            $name = $access = $form->hiddens[Operation::NAME];
            if ($name == 'save') {
                $access = Module::PERMISSION_CREATE;
            } else {
                if ($name == 'post' && $destination == 'forms') {
                    $access = 'post form';
                }
            }
            if (!$core->user->has_permission($access, $destination)) {
                return (string) new \Brickrouge\Alert(<<<EOT
<p>You don't have permission to execute the <q>{$name}</q> operation on the <q>{$destination}</q> module,
<a href="{$core->site->path}/admin/users.roles">the <q>{$core->user->role->name}</q> role should be modified</a>.</p>
EOT
, array(), 'error');
            }
        }
        $core->document->css->add(DIR . 'public/page.css');
        $before = $this->before;
        $after = $this->after;
        $form = $this->form;
        new Form\BeforeRenderEvent($this, array('before' => &$before, 'after' => &$after, 'form' => $form));
        $normalized = \ICanBoogie\normalize($this->slug);
        if ($before) {
            $before = '<div class="form-before form-before--' . $normalized . '">' . $before . '</div>';
        }
        if ($after) {
            $after = '<div class="form-after form-after--' . $normalized . '">' . $after . '</div>';
        }
        $html = $before . $form . $after;
        new Form\RenderEvent($this, array('html' => &$html, 'before' => $before, 'after' => $after, 'form' => $form));
        return $html;
    }
예제 #9
0
    /**
     * Returns the HTML representation of the view element and its content.
     *
     * @return string
     */
    protected function render_outer_html()
    {
        $class = '';
        $type = \ICanBoogie\normalize($this->type);
        $m = $this->module;
        while ($m) {
            $normalized_id = \ICanBoogie\normalize($m->id);
            $class = "view--{$normalized_id}--{$type} {$class}";
            $m = $m->parent;
        }
        $this->element = new Element('div', ['id' => 'view-' . \ICanBoogie\normalize($this->id), 'class' => trim("view view--{$type} {$class}"), 'data-constructor' => $this->module->id]);
        $this->element = $this->alter_element($this->element);
        #
        $html = $o_html = $this->render_inner_html($this->engine->context);
        new RenderEvent($this, $html);
        #
        if (Debug::is_dev()) {
            $possible_templates = implode(PHP_EOL, $this->template_tries);
            $html = <<<EOT

<!-- Possible templates for view "{$this->id}":

{$possible_templates}

-->
{$html}
EOT;
        }
        $this->element[Element::INNER_HTML] = $html;
        $this->element['data-template-path'] = $this->template_pathname;
        return (string) $this->element;
    }
예제 #10
0
 /**
  * Decorates a header content with a `TH` element.
  *
  * @param string $content
  * @param string $column_column_id
  *
  * @return Element
  */
 protected function decorate_header($content, $column_column_id)
 {
     return new Element('th', [Element::INNER_HTML => $content ?: '&nbsp;', 'class' => 'header--' . \ICanBoogie\normalize($column_column_id)]);
 }
예제 #11
0
 /**
  * Replaces `type` value by "page" and `id` value by "page-id-<nid>".
  *
  * The following class names are added:
  *
  * - `slug`: "page-slug-<slug>"
  * - `home`: true if the page is the home page.
  * - `active`: true if the page is the active page.
  * - `trail`: true if the page is in the breadcrumb trail.
  * - `node-id`: "node-id-<nid>" if the page displays a node.
  * - `node-constructor`: "node-constructor-<normalized_constructor>" if the page displays a node.
  * - `template`: "template-<name>" the name of the page's template, without its extension.
  */
 protected function get_css_class_names()
 {
     $names = array_merge(parent::get_css_class_names(), array('type' => 'page', 'id' => 'page-id-' . $this->nid, 'slug' => 'page-slug-' . $this->slug, 'home' => $this->home->nid == $this->nid, 'active' => $this->is_active, 'trail' => $this->is_trail, 'template' => 'template-' . preg_replace('#\\.(html|php)$#', '', $this->template), 'has-children' => count($this->navigation_children) != 0));
     if (isset($this->node)) {
         $node = $this->node;
         $names['node-id'] = 'node-id-' . $node->nid;
         $names['node-constructor'] = 'node-constructor-' . \ICanBoogie\normalize($node->constructor);
     }
     return $names;
 }
예제 #12
0
 private static function slugize($str, $language = null)
 {
     return \ICanBoogie\normalize($str);
 }
 /**
  * Creates a nonce login ticket.
  *
  * If a previous ticket for the user exists it will be deleted.
  */
 protected function process()
 {
     global $core;
     $user = $this->record;
     $model = $this->module->model;
     # delete previous ticket (if any)
     $model->filter_by_uid($user->uid)->delete();
     # create new ticket
     $ticket = Ticket::from(array('uid' => $user->uid, 'token' => $model->generate_token(), 'expire_at' => '+' . Module::FRESH_PERIOD . ' seconds', 'ip' => $this->request->ip));
     $ticket->save();
     $this->ticket = $ticket;
     $this->response->message = new FormattedString('success', array('%email' => $user->email), array('scope' => \ICanBoogie\normalize($user->constructor, '_') . '.nonce_login_request.operation'));
     return true;
 }
예제 #14
0
 /**
  * Returns the CSS class names of the node.
  *
  * @return array[string]mixed
  */
 protected function get_css_class_names()
 {
     return ['type' => 'user', 'id' => $this->uid && !$this->is_guest ? 'user-id-' . $this->uid : null, 'username' => $this->username && !$this->is_guest ? 'user-' . $this->username : null, 'constructor' => 'constructor-' . \ICanBoogie\normalize($this->constructor), 'is-admin' => $this->is_admin, 'is-guest' => $this->is_guest, 'is-logged' => !$this->is_guest];
 }